HypeConversa
API Reference

Conecte o WhatsApp ao seu produto com uma API previsível.

Um contrato previsível, adaptado à segurança, aos escopos e à arquitetura multiempresa do HypeConversa.

Credenciais para experimentar

Os valores ficam apenas nesta aba durante a sessão e são usados somente ao clicar em Experimentar.

Comece aqui

Visão geral

Todas as requisições usam HTTPS e corpos JSON. A URL abaixo mostra onde o token da instância entra no caminho:

url
https://api.hypeconversa.com/instances/{INSTANCE_TOKEN}
Abra qualquer endpoint e use Experimentar. As credenciais preenchidas acima serão inseridas na URL e no header somente no momento da chamada.

Segurança

Autenticação em duas camadas

Cada chamada combina exatamente dois segredos: o token da conta no header e o token da instância na URL. Os dois precisam estar ativos e pertencer ao mesmo tenant.

1. Token da conta
Client-Token

Autoriza o tenant e pode ser rotacionado globalmente.

2. Token da instância
INSTANCE_TOKEN

Identifica a conexão e aplica seus escopos exclusivos.

Envie o token da conta sem Bearer:

http
Client-Token: hca_SEU_TOKEN_DE_CONTA

E monte a rota da instância neste formato:

url
/instances/INSTANCE_TOKEN/send-text
O token da instância está na URL para identificar a conexão. Use somente HTTPS e configure o proxy, APM e access logs para ocultar o segmento após /instances/. O HypeConversa já remove esse valor dos próprios logs de aplicação.

Destinatário

Nos envios, phone é o número de destino em formato internacional, somente com dígitos: DDI + DDD + número. Não inclua +, espaços ou traços. Exemplo: 5511999999999.

Para grupos, use o jid devolvido pela API, como [email protected].

Paginação por página

Listas longas usam os parâmetros page e pageSize. A primeira página é 1 e cada página pode conter até 100 itens.

json
{
  "items": [ ... ],
  "page": 1,
  "pageSize": 20,
  "total": 42,
  "totalPages": 3
}

Para carregar a próxima página, incremente page até alcançar totalPages.

Idempotência sem duplicidade

Em POSTs de envio, use uma chave única por operação. O valor deve ter entre 8 e 128 caracteres alfanuméricos e pode conter ponto, sublinhado, dois-pontos ou hífen.

http
Idempotency-Key: pedido:12345
A mesma chave, rota e corpo retornam a resposta já concluída por até 24 horas. Reutilizar a chave com outro corpo gera 409. Uma repetição simultânea também recebe 409 com Retry-After: 1.

Limites de uso

Cada token de instância aceita até 120 requisições por minuto. Há também uma proteção global por IP contra abuso.

Ao exceder o limite, a API responde 429 e informa Retry-After. Respeite também o ritmo do WhatsApp para reduzir risco de bloqueio da conta.

Erros consistentes

Erros usam um código estável e uma mensagem legível por máquina:

json
{
  "code": "VALIDATION_ERROR",
  "message": "VALIDATION_ERROR",
  "fieldErrors": {}
}
  • 400 requisição inválida ou conexão desconectada.
  • 401 credenciais ausentes, inválidas, revogadas ou incompatíveis.
  • 403 o token da instância não possui o escopo necessário.
  • 404 recurso não encontrado dentro da conta autenticada.
  • 409 conflito de idempotência ou estado.
  • 422 corpo ou parâmetros fora do contrato.
  • 429 limite de uso atingido.
  • 503 gateway do WhatsApp temporariamente indisponível.

HypeCom

Identificar o usuário logado

O HypeCom é instalado com uma linha no HTML. A chave pública da conexão sai no painel, em Conexões:

html
<script
  src="function(){throw Error("Attempted to call HYPECOM_EDGE_URL() from the server but HYPECOM_EDGE_URL is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")}/widget.js"
  data-public-key="CHAVE_PUBLICA_DA_CONEXAO"
></script>

Para abrir ou fechar com um botão do próprio site, use a API pública do widget:

js
window.hypecom('open');
window.hypecom('close');
window.hypecom('toggle');

Se o atendimento deve aparecer somente por esse gatilho, oculte o botão flutuante na instalação:

html
<script
  src="function(){throw Error("Attempted to call HYPECOM_EDGE_URL() from the server but HYPECOM_EDGE_URL is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")}/widget.js"
  data-public-key="CHAVE_PUBLICA_DA_CONEXAO"
  data-hide-launcher="true"
></script>

Assim ele já atende visitante anônimo. O que muda bastante é a continuidade da conversa, e os dois modos convivem na mesma instalação:

Continuidade por navegador

Visitante anônimo

  • A credencial fica no armazenamento do seu site, em primeira parte.
  • Vale 270 dias e é renovada a cada visita.
  • Presa à origem exata e trocada por sessão só no bootstrap.
  • Não recupera a conversa em outro dispositivo: não existe identidade para ligar os dois.

Identidade da conta

Usuário logado

  • A âncora é o sub do token que o seu backend assina.
  • A mesma pessoa reencontra as conversas em qualquer dispositivo onde esteja logada.
  • Não depende de cookie nem de armazenamento do navegador.
  • E-mail e telefone do token chegam como dados verificados, não como algo que o visitante digitou.

Para identificar, o seu backend assina um JWT HS256 com o segredo da conexão. Ele nasce em Conexões, na conexão do HypeCom, no bloco Verificação de identidade, botão Gerar segredo. É exibido uma única vez, ali: o banco guarda a versão cifrada e nem o painel consegue lê-la de volta. Enquanto não houver segredo gerado, a conexão recusa qualquer token com WEB_CHAT_IDENTITY_VERIFICATION_DISABLED.

backend
import { createHmac, randomUUID } from 'node:crypto';

const secret = process.env.HYPECOM_IDENTITY_SECRET; // whs_...
const part = (value) => Buffer.from(JSON.stringify(value)).toString('base64url');

export function hypecomIdentityToken(user) {
  const now = Math.floor(Date.now() / 1000);
  const header = part({ alg: 'HS256', typ: 'JWT' });
  const payload = part({
    sub: user.id,      // id interno e estável. Nunca o e-mail: e-mail muda.
    name: user.name,
    email: user.email, // opcional, e chega como dado verificado
    phone: user.phone, // opcional
    iat: now,
    exp: now + 3600,
    jti: randomUUID(), // um por token: é o que barra reuso
  });
  const signature = createHmac('sha256', secret)
    .update(`${header}.${payload}`)
    .digest('base64url');
  return `${header}.${payload}.${signature}`;
}

Renderize um token novo em cada carga de página:

html
<script
  src="function(){throw Error("Attempted to call HYPECOM_EDGE_URL() from the server but HYPECOM_EDGE_URL is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")}/widget.js"
  data-public-key="CHAVE_PUBLICA_DA_CONEXAO"
  data-identity-token="<%= hypecomIdentityToken(currentUser) %>"
></script>

E cubra os dois momentos que não passam por uma nova carga, o login numa aplicação de página única e o logout:

js
// Login sem recarregar a página
const { token } = await fetch('/api/hypecom/identity-token').then((r) => r.json());
window.hypecom('identify', { identityToken: token });

// Logout, sempre
window.hypecom('shutdown');
O segredo vive somente no seu servidor. Se ele aparecer no JavaScript da página, qualquer visitante consegue se autenticar como qualquer usuário do seu sistema.

Claims aceitas no token:

  • sub obrigatório. O identificador estável do usuário no seu sistema, e é ele que amarra a mesma pessoa entre dispositivos.
  • exp obrigatório, com validade máxima de 24 horas. Token de identificação sem prazo vira credencial eterna se vazar do HTML.
  • jti recomendado, único por emissão. É o que impede o reuso do mesmo token.
  • email, phone e name opcionais. Como vêm assinados, são tratados como verificados, e o vínculo automático com um contato existente só acontece quando exatamente um contato casa com eles.
Ao identificar, a conversa anônima daquele navegador é incorporada à identidade da conta, então o visitante não perde o que acabou de escrever ao entrar. Uma identidade já vinculada a outro contato nunca é absorvida.
Chame shutdown no logout. Sem ele a sessão continua válida e, num computador compartilhado, o próximo usuário abre o HypeCom na conversa de quem saiu.
Token inválido, expirado ou com jti repetido é recusado, e o HypeCom não cai para anônimo em silêncio: degradar caladinho faria o seu site acreditar que está identificando o usuário com a integração quebrada. Confira também se a origem exata do site, com esquema e porta, está na lista de sites permitidos da conexão.

A recusa é avisada à sua página, com o motivo. A conversa que já estava acontecendo continua de pé como visitante anônimo, porque derrubá-la deixaria quem estava escrevendo sem resposta nenhuma:

js
window.addEventListener('message', (event) => {
  if (event.origin !== 'function(){throw Error("Attempted to call HYPECOM_EDGE_URL() from the server but HYPECOM_EDGE_URL is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")}') return;
  if (event.data?.type !== 'hypecom:identify-failed') return;
  // event.data.code diz o motivo, por exemplo:
  //   WEB_CHAT_IDENTITY_VERIFICATION_DISABLED  segredo nao gerado na conexao
  //   WEB_CHAT_IDENTITY_TOKEN_INVALID          assinatura, prazo ou jti repetido
  console.error('Hypecom: identidade recusada', event.data.code);
});