DOCUMENTAÇÃO DA API
Integre seu sistema ao SeeZap.
Crie instâncias, conecte números por QR Code ou código de vinculação, envie mensagens e receba eventos em uma API HTTP JSON.
URL base
https://seezap.com.br/v1
O contrato completo de integração está em OpenAPI 3.1 (JSON). Consulte GET /v1/capabilities e GET /v1/instances/{id}/capabilities para suporte por canal, escopos, limites, conexão e retenção desta implantação. Recursos novos mantêm a versão /v1 e eventos com version:1.
Autenticação
Use uma API key criada no painel. O segredo é exibido somente uma vez.
Chaves podem ser limitadas por instância e operação. Crie-as em POST /v1/api-keys com permissions:{scopes:["conversations:read","messages:read","history:read","capabilities:read"],instanceIds:["ID"]}. Chaves antigas sem permissões explícitas preservam seu acesso. Não inclua segredos em páginas públicas. Gestão de chaves exige a sessão do painel; revogue chaves na tela Segurança.
Authorization: Bearer sk_live_sua_chave
Instâncias
Cada instância representa um número conectado e uma unidade contratada.
Criar instância QR
POST /v1/instances
{
"name": "Atendimento",
"channel": "qr"
}
Conectar
POST /v1/instances/{id}/connect
Consultar QR Code
GET /v1/instances/{id}/qr
Conectar por código (alternativa ao QR Code)
No painel, informe somente DDD + celular, no formato (11) 99999-9999. O código do Brasil (55) é acrescentado automaticamente na chamada à API.
POST /v1/instances/{id}/pairing-code
{ "phoneNumber": "5511999999999" }
HTTP 200
{ "code": "ABCD1234" }
Use o número completo com DDI e DDD. A API aceita espaços e pontuação e normaliza os dígitos. O canal permanece qr; não é necessário criar outra instância. A solicitação inicia a conexão e aguarda o WhatsApp preparar a vinculação. No celular, abra Aparelhos conectados → Conectar um aparelho → Conectar com número de telefone e digite o código. Não é um SMS.
O código é temporário e não deve ser armazenado em logs ou compartilhado. Solicitações para o mesmo número reutilizam o código por até um minuto; aguarde esse intervalo antes de solicitar outro. Limite de cinco requisições por minuto por credencial. HTTP 409 indica sessão já pareada ou geração conflitante; HTTP 503 indica indisponibilidade temporária. Consulte GET /v1/instances/{id} até liveStatus=connected. A conclusão exige ação do titular no celular.
A criação retorna HTTP 201 com id, name, channel e status. Conectar retorna {"connecting":true}. Consulte o QR enquanto a instância conecta: {"status":"connecting","qr":"data:image/png;base64,..."}. O QR expira e é atualizado. Não compartilhe seu conteúdo.
POST /v1/instances/{id}/disconnect encerra o pareamento; DELETE /v1/instances/{id} remove a instância e seu histórico. O reinício do servidor preserva o pareamento quando ainda autorizado pelo WhatsApp e pela assinatura.
Mensagens
Enviar texto
POST /v1/messages
{
"instanceId": "instancia_id",
"to": "5511999999999",
"type": "text",
"text": "Olá"
}
No canal QR: text, image, audio, video, document, sticker, location, contact e poll. Para mídias, informe mediaUrl. Menções usam mentions com JIDs; respostas usam quotedMessageId de mensagem retida. Destinos QR aceitam telefone, JID individual, LID ou grupo. Consulte no OpenAPI os campos de localização, vCard, enquete, MIME e nota de voz. O conector oficial mantém cinco tipos básicos e rejeita opções exclusivas de QR.
Repetição segura e acompanhamento
Envie Idempotency-Key com 16 a 128 caracteres, única por operação da conta. A mesma chave com o mesmo corpo retorna a mensagem já criada; outro corpo é rejeitado. A garantia vale enquanto o registro estiver retido. Uma resposta HTTP 202 confirma a persistência para processamento e retorna {"id":"...","status":"queued"}; não confirma entrega.
GET /v1/messages?instanceId=ID&limit=50
{ "data": [{ "id": "...", "direction": "outbound", "type": "text", "status": "sent", "createdAt": "..." }] }
O tamanho de cada página é de 1 a 200. A resposta contém data, hasMore e nextCursor. Para buscar as anteriores, repita os mesmos filtros com cursor=nextCursor até hasMore=false. A ordem é sentAt e id decrescentes. Estados: queued, sending, sent, delivered, read, failed, uncertain e received. Uma interrupção após iniciar o envio pode produzir uncertain. Esse envio não é repetido automaticamente; confirme o resultado antes de criar outra operação. Sem conexão ou acesso vigente, a mensagem aguarda até 24 horas e então falha.
Conversas e histórico
Filtre mensagens por conversationJid, from (ISO inclusivo), to (ISO exclusivo), direction, type e source. Preserve externalId, rawKey, participantJid, senderJid e fromMe. originalTimestamp é o horário do WhatsApp quando conhecido; sentAt pode conter fallback, enquanto receivedAt e createdAt indicam observação e armazenamento. LIDs são identificadores opacos e não devem virar telefones. Mensagens do celular aparecem como saída; histórico e mensagens próprias não disparam message.inbound.
POST /v1/instances/ID/history
{"messageId":"ID_DA_MENSAGEM_MAIS_ANTIGA","count":50}
Solicita até 100 mensagens anteriores, com conexão e acesso vigente. Use Idempotency-Key para repetir a consulta à mesma intenção. Leia state: 202 pode indicar aceite ou resultado incerto. Consulte GET /v1/instances/{id}/sync e /history-requests. Progresso e períodos observados não provam cobertura contínua. completeness=unverified permanece explícito; hasMore=false significa somente fim do banco consultado. Não há garantia de recuperar todo o histórico ou anexos expirados.
Arquivos
POST /v1/messages
Idempotency-Key: sua-operacao-documento-001
{
"instanceId": "ID", "to": "5511999999999", "type": "document",
"mediaUrl": "https://seu-servidor.com/arquivo.pdf", "filename": "arquivo.pdf"
}
A URL de origem deve ser pública, sem credenciais embutidas ou redirecionamentos. Endereços privados e locais são bloqueados. O limite é 32 MiB por mídia. Imagens e vídeos podem receber caption. A mídia inbound é baixada, armazenada com criptografia e expira em sete dias por padrão. O evento inclui mediaUrl e mediaExpiresAt; baixe essa URL usando sua chave Bearer. HTTP 404 significa mídia ausente, expirada ou de outra conta. mediaError explica falhas de obtenção.
Conversas e integração da Agenda
Contatos, conversas e mensagens são recursos distintos. GET /v1/conversations inclui conversas conhecidas sem mensagem armazenada. GET /v1/contacts lista identidades; um contato não prova conversa ativa.
GET /v1/conversations?instanceId=ID&order=alphabetical&view=all&limit=100
GET /v1/conversations?instanceId=ID&order=whatsapp&view=main&limit=100
Os objetos incluem ID/JID, tipo, nome, contato/foto, atividade, última mensagem acessível, arquivamento, fixação, posição derivada, contagem de não lidas e remoção. Valores null representam estado desconhecido. view=main inclui somente conversas observadas como não arquivadas e não removidas; use state=unknown para identificar registros aguardando sincronização. Há filtros por tipo, nome/JID, removidas, fixadas e não lidas.
A ordem usa fixação observada, atividade e desempate estável. pinPosition é derivada e exactWhatsAppOrder=false: a posição específica no celular e suas listas personalizadas não são comprovadas. view=archived lista arquivadas separadamente.
Continue com nextCursor e os mesmos filtros. Se a lista mudar durante a coleta, HTTP 409 cursor_stale exige reiniciar a paginação. Crie a assinatura antes da carga, guarde eventos durante a leitura, substitua a lista apenas quando todas as páginas terminarem e aplique as alterações recebidas. Não use mensagens para inferir a lista principal.
Operações e capacidades
Descubra suporte por instância com GET /v1/instances/{id}/capabilities: supported, partial ou unavailable, motivo, escopo e disponibilidade atual. A API não presume paridade entre QR, oficial e mock.
POST /v1/instances/ID/operations
Idempotency-Key: agenda-fixar-conversa-001
{"kind":"chat.pin","jid":"5511999999999@s.whatsapp.net","pin":true}
Operações QR cobrem consultas/gestão de grupos, perfil/foto, presença, arquivar/fixar/silenciar/marcar conversa, reações, edição, exclusão, encaminhamento, leitura, estrela e rejeição de chamada. Todos os corpos são discriminados por kind e validados no OpenAPI; não há execução de métodos arbitrários. Escritas exigem chave de idempotência e escopo específico.
Consulte GET /v1/instances/{id}/operations/{operationId}. requested, confirmed, failed e uncertain distinguem resultado; término da chamada não prova atualização em todos os dispositivos. Não repita ações incertas automaticamente. Referências/encaminhamentos precisam do conteúdo original retido; regras de autoria, prazo, grupo e privacidade continuam aplicáveis.
Chamadas só expõem sinalização e rejeição, sem áudio/vídeo. Stories, newsletters, templates, Flows e comércio não estão implementados no contrato. GET /v1/instances/{id}/diagnostics informa conexão, sincronização, retenção e entregas com falha.
Webhooks
Cadastre um endpoint HTTPS pelo painel ou em POST /v1/webhooks. Cada entrega inclui X-SeeZap-Signature e X-SeeZap-Event.
POST /v1/webhooks
{ "url":"https://seu-servidor.com/seezap", "instanceId":"ID", "events":["message.inbound","message.status"] }
O retorno HTTP 201 contém id, url, events e secret. Guardar a mesma URL, instância e eventos atualiza a configuração. Omitir instanceId assina eventos de toda a conta quando a chave permite. Para preservar integrações existentes, ["*"] recebe somente instance.status, message.inbound e message.status. Assine os novos nomes explicitamente e conceda seus escopos de leitura.
A assinatura usa HMAC-SHA256 sobre o timestamp e o corpo bruto, no formato documentado abaixo. Não transforme o JSON antes de verificar. Compare a assinatura em tempo constante, rejeite timestamps antigos e deduplique pelo id do envelope. Entregas são pelo menos uma vez: uma resposta perdida pode causar repetição.
X-SeeZap-Signature: t=1789257600000,v1=HEXADECIMAL_HMAC
X-SeeZap-Event: message.inbound
X-SeeZap-Delivery: ID_DA_ENTREGA
// Node.js: rawBody deve conter os bytes JSON recebidos, sem reserialização.
const expected = createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`).digest();
const received = Buffer.from(v1, 'hex');
const valid = Number.isFinite(timestamp)
&& Math.abs(Date.now() - timestamp) <= 300000
&& received.length === expected.length
&& timingSafeEqual(received, expected);
Importe createHmac e timingSafeEqual de node:crypto. O timestamp é expresso em milissegundos, com tolerância sugerida de cinco minutos. Cada tentativa gera uma assinatura atual; o identificador do evento permanece estável.
Consulte GET /v1/webhook-deliveries?instanceId=ID&limit=100 e percorra nextCursor para recuperar todos os envelopes retidos; filtre status quando necessário. Há até seis tentativas automáticas, com espera exponencial iniciada em três segundos. Responda HTTP 2xx em até dez segundos após persistir o evento. Corrigido o destino, solicite POST /v1/webhook-deliveries/{id}/retry. A reentrega mantém o ID de evento. Não há recuperação de eventos que o WhatsApp nunca entregou.
Eventos
Além dos três eventos legados: message.own, message.history, message.updated, message.deleted, message.reaction, message.receipt, conversation.updated, conversation.deleted, contact.updated, history.sync, group.updated, presence.updated, call.updated, operation.requested e operation.updated. Consulte o catálogo da implantação para confirmar os nomes.
Use message.history para importar e message.own para atualizar mensagens do próprio número. Esses eventos não devem disparar automações de novas entradas da Agenda. Atualize a lista por eventos de conversa/contato e deduplique todos os eventos pelo ID.
{
"id":"evt_...", "event":"message.inbound", "version":1,
"instanceId":"ID", "createdAt":"2026-09-13T00:00:00.000Z",
"data":{"id":"...","externalId":"...","from":"5511999999999","type":"text","text":"Olá","timestamp":1789257600000}
}
instance.status contém status, número quando disponível, erro e QR quando emitido; por isso exige instances:write, inclusive via assinatura ["*"]. Chaves de leitura consultam conexão em GET /v1/instances/{id}, sem QR. message.status contém a identificação externa e o status confirmado. Sua aplicação deve aceitar campos opcionais e novos campos compatíveis dentro da versão.
Escopo e limites
A oferta comercial atual possui somente o canal qr. Monitor, canal oficial e mock não fazem parte do produto exposto.
Envio: até 120 requisições por minuto por credencial, operações até 60, pedidos de histórico até 3, além do limite global de 600/minuto. Mensagens e eventos ficam retidos por trinta dias desde armazenamento e bytes de anexos por sete dias, por padrão. Consulte os valores reais em capabilities. Conversas/contatos permanecem até remover a instância. Corpos de operações expiram, enquanto chave e resultado de estado permanecem para impedir repetição da intenção. Estatísticas usam apenas registros retidos. Não há compatibilidade automática com APIs de terceiros.
Erros usam HTTP 400 para entrada inválida, 401 para autenticação ausente ou expirada, 402 para acesso/quantidade insuficiente, 403 para operação vedada, 404 para recurso inexistente, 409 para conflito, 429 para excesso de requisições e 5xx para falha temporária. Em caso de 429 respeite Retry-After. Repetir checkout exige a mesma chave de idempotência para evitar contratação duplicada.
Consulte também os Termos de Uso e a Política de Privacidade antes de operar números em produção.