O que é a API NimoChat Pro+
A API NimoChat Pro+ é uma interface REST que permite integrar a plataforma de atendimento com qualquer sistema externo: CRM, ERP, sistema de RH, plataformas de automação como n8n, Make, Zapier, ou aplicações sob medida.
Com a API você pode automatizar tarefas repetitivas, sincronizar dados entre sistemas, criar fluxos personalizados e levar a inteligência do NimoChat Pro+ para fora dele. A API é organizada em torno de princípios REST: usa URLs previsíveis, recebe e devolve JSON, e usa códigos HTTP padrão.
Casos de uso comuns
- Disparo em massa segmentado — Buscar contatos com determinada tag e disparar campanha via n8n.
- Sincronização com CRM — Criar contatos automaticamente a partir de leads do seu CRM.
- Automação de RH — Cadastrar usuários (atendentes) automaticamente quando um colaborador é admitido no ERP.
- Integração com BI — Extrair dashboards de tickets, tempos de atendimento e evolução para Power BI / Looker.
- Humanização de bots — Mostrar status "digitando..." antes de uma resposta automática.
Começando
Para usar a API você precisa de 3 informações: a URL base do seu painel, uma chave de API (token) e o ID da sua conexão WhatsApp. Tudo pode ser obtido em poucos cliques no painel administrativo.
Passo 1 — Gerar sua chave de API
- Faça login no seu painel NimoChat Pro+ como Administrador.
- No menu lateral, acesse API.
- Clique em Nova API, dê um nome e selecione a conexão WhatsApp.
- Copie e guarde o Token e o API ID. O token só é exibido uma vez.
Passo 2 — Identificar sua URL base
Cada cliente NimoChat Pro+ tem sua própria URL de back-end. Ela aparece no painel administrativo e tem o formato:
https://gestor.nimochat.com.br // contas do Atende https://atende1admin.nimochat.com.br // contas do Atende1
Atenção: o endereço da API não é o mesmo que você usa para entrar no painel. O painel é a tela em que você faz login; a API atende num endereço próprio. Se você usar o endereço do painel nas chamadas, elas serão redirecionadas para a tela de login e nada funcionará, sem uma mensagem de erro que explique o motivo.
Para descobrir qual é o seu, veja por onde você acessa o painel:
| Se você acessa o painel em | a URL base da sua API é |
|---|---|
atende.nimochat.com.br ou hub.nimochat.com.br | https://gestor.nimochat.com.br |
atende1.nimochat.com.br ou hub1.nimochat.com.br | https://atende1admin.nimochat.com.br |
Na dúvida, fale com o suporte antes de começar a integração: usar o endereço errado é o motivo mais comum de a primeira chamada não responder.
Autenticação
A API NimoChat Pro+ usa o padrão Bearer Token. Toda requisição precisa incluir o token no cabeçalho HTTP Authorization:
Authorization: Bearer SEU_TOKEN_AQUI
O sistema valida o token em todas as chamadas e isola os dados por empresa: você só consegue acessar e modificar dados da sua própria conta. Tentar usar um token inválido, ou esquecer o cabeçalho, retorna HTTP 403 Forbidden com {"error": "Invalid token."} ou {"error": "Token was not provided."}.
.env), nunca direto no código. Em ambientes de produção, use um cofre de secrets como AWS Secrets Manager, Doppler ou Vault.
URL Base e formato dos endpoints
Todos os endpoints da API seguem o mesmo padrão de URL:
https://SUA_URL_BASE/v2/api/external/{apiId}/{endpoint}
Onde:
SUA_URL_BASE— o endereço da API da sua conta (veja a tabela no Passo 2 acima; não é o endereço do painel){apiId}— o API ID gerado no Passo 1{endpoint}— o nome do endpoint que você quer chamar (ex:listChannels)
Convenções da API
Formato de datas
Onde houver filtro por período (startDate, endDate), use o
formato ano-mês-dia: 2026-08-21. O formato brasileiro
21/08/2026 não funciona e provoca um erro
500, que parece falha do servidor mas é só o formato errado.
?startDate=2026-08-01&endDate=2026-08-21 // certo ?startDate=01/08/2026&endDate=21/08/2026 // erro 500
Onde vem a lista nas listagens
Toda resposta traz success e data, mas o lugar da lista
dentro de data muda conforme o endpoint. Confira antes de programar
o laço, para não escrever um código que funciona numa rota e quebra na outra:
| Onde está a lista | Endpoints |
|---|---|
data (a própria lista) | listContacts, listTickets, listTags, listUsers, listQueues, todo/list, gallery/list |
data.campaigns | campaign/list |
data.data | pipeline/list, listOpportunities |
Paginação
Quase toda listagem traz um bloco pagination ao lado de data.
O campo total está sempre presente; os demais variam por
endpoint, então não assuma que o bloco é igual em todos:
Campos do pagination | Endpoints |
|---|---|
total | listTags, listQueues, listSessions |
total, hasMore | listContacts, listTickets, listUsers, gallery/list |
total, page, limit, hasMore | appointment/list, bulkDispatch/list, searchMessages |
total, page, limit, totalPages | callLog/list, pipeline/list, listOpportunities |
page, limit, total, totalPages, hasMore | contacts/search |
| não traz o bloco | listChatFlows, todo/list, campaign/list |
listContacts o total vem
como texto ("3068") e não como número: converta antes de
comparar ou somar. E em pipeline/list e listOpportunities o
bloco pagination fica dentro de data, não ao
lado dele.
Nos três endpoints que não trazem o bloco, peça a próxima página (pageNumber,
quando disponível) até vir uma lista vazia.
Ritmo de chamadas
Não publicamos um limite fixo de requisições por minuto, e em uso normal a API não
bloqueia: em teste, 30 chamadas seguidas foram todas respondidas. Ainda assim, evite
rajadas grandes em paralelo, principalmente em importações: prefira sequencial, ou poucas
chamadas simultâneas. Se algum dia receber 429, espere alguns segundos e
repita a chamada.
Códigos de resposta
| Código | Significado |
|---|---|
200 OK | Requisição bem-sucedida. O corpo contém os dados solicitados. |
201 Created | Registro criado. Algumas rotas de criação respondem 201 em vez de 200 (ex: createNotes). Trate os dois como sucesso. |
400 Bad Request | Parâmetros inválidos ou faltando. |
403 Forbidden | Token inválido, ausente, ou sem permissão para o recurso. O corpo traz {"error": "Invalid token."} ou {"error": "Token was not provided."}. |
402 Payment Required | O plano da conta não inclui o recurso (ERR_FEATURE_NOT_IN_PLAN) ou a conta está bloqueada por pagamento (ERR_TENANT_PAYMENT_BLOCKED). |
404 Not Found | Recurso não encontrado (ex: ID inexistente ou de outra conta). |
409 Conflict | A ação conflita com o estado atual. Ex: enviar para um ticket fechado sem pedir para reabrir (ERR_TICKET_CLOSED). |
413 Payload Too Large | Envio grande demais (ex: respostas de formulário acima de 32 KB, cota da galeria estourada). |
422 Unprocessable Entity | O número informado corresponde a mais de um contato (ERR_NUMBER_AMBIGUOUS). A resposta traz os candidatos: nas rotas que aceitam contactId (ex: telegramInvite), repita a chamada com ele. |
424 Failed Dependency | Um serviço externo não respondeu. Ex: ERR_WAPP_CONTACT_UNVERIFIED (número sem WhatsApp, ou a consulta ao WhatsApp falhou na hora). Pode tentar de novo. |
429 Too Many Requests | Chamadas demais em pouco tempo. Não há um limite fixo publicado (veja Convenções). Se receber, aguarde alguns segundos e tente de novo. |
500 Internal Server Error | Erro no servidor. Reporte ao suporte se persistir. |
error. Quase todo erro traz um código como {"error": "ERR_MISSING_FIELDS", "fields": ["userId"]}. Quando vier field ou fields, eles dizem exatamente qual campo corrigir. Os códigos de cada rota estão no cartão dela.Exemplo rápido — sua primeira chamada
Vamos listar todos os canais (conexões WhatsApp) da sua conta. Substitua SEU_TOKEN, SUA_URL_BASE e SEU_API_ID pelos valores reais:
cURL
curl --request GET \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/listChannels' \ --header 'Authorization: Bearer SEU_TOKEN'
Resposta esperada
{
"success": true,
"data": [
{
"id": 1,
"name": "WhatsApp Principal",
"type": "whatsapp",
"status": "CONNECTED",
"number": "5511999999999",
"isActive": true
}
]
}
success e data: os dados que você quer estão sempre dentro de
data, nunca na raiz. Em caso de erro, vem {"error": "MENSAGEM"}.
Ao programar, leia resposta.data e não resposta.channels ou
resposta.contacts.
🤖 Usando a API com uma IA
Se você vai pedir para uma IA (ChatGPT, Claude, Gemini, Copilot ou outra) escrever a sua integração, entregue a ela o endereço desta página e o bloco abaixo. As IAs costumam completar o que não sabem com o que viram em outras plataformas parecidas, e erram justamente nos pontos listados, que conferimos no nosso servidor.
- Copie o bloco Regras para a IA e cole no começo da conversa.
- Se a IA consegue abrir links, passe também o endereço
clientes.nimochat.com.br/llms-full.txt: é esta documentação inteira em texto, que a IA lê melhor do que a página. - Peça uma rota de cada vez e teste cada uma antes de seguir (o Exemplo rápido serve de primeiro teste).
- Quando der erro, cole na conversa a resposta inteira da API: o código em
errordiz o que corrigir.
SEU_TOKEN
e coloque o valor real só no seu servidor, numa variável de ambiente. Quem tem o token envia mensagens
em nome da sua empresa.Regras para a IA (copie e cole no começo da conversa)
Você vai escrever uma integração com a API do NimoChat Pro+.
Use SÓ as rotas e os campos da documentação oficial:
https://clientes.nimochat.com.br/documentacaoapiproplus.php
(a mesma documentação em texto: https://clientes.nimochat.com.br/llms-full.txt)
Se precisar de algo que não está lá, pergunte. Não invente rota nem campo.
Regras conferidas no nosso servidor (última conferência em 29/10/2026):
1. URL: https://SUA_URL_BASE/v2/api/external/{apiId}/{rota}. A URL base da API
não é o endereço do painel (tabela no Passo 2 da documentação).
2. Autenticação: header "Authorization: Bearer SEU_TOKEN". Token errado ou
ausente responde 403 (não 401). Exceção: no envio por GET (/params/) o
token vai no parâmetro bearertoken da URL, e o header é ignorado. Nunca
escreva o token no código: leia de uma variável de ambiente.
3. Rotas GET leem só a URL (caminho e query string). Filtro no corpo é
ignorado sem erro.
4. Filtros de período (startDate, endDate) em AAAA-MM-DD. DD/MM/AAAA nesses
filtros dá erro 500. Exceções: birthdayDate do contato é DD/MM/AAAA; datas de
agendamento aceitam os dois; em tarefas (todo) use AAAA-MM-DD, porque com
barra a data é lida como mês/dia (02/03 vira 3 de fevereiro).
5. Hora sem fuso vale o horário de Brasília (-03:00). Prefira mandar o fuso.
6. updateContact encontra o contato pelo campo number. Não existe contactId
nessa rota; sem number a resposta é 500.
7. createTicket exige userId. sendLocation e sendVcard exigem ticketId.
8. Várias tags: campo tagIds (lista). Lista dentro de tagId dá erro.
9. updatetag SUBSTITUI todas as tags do contato. Para acrescentar, use addTag
ou addTagContact.
10. createContact, updateContact, addTag e removeTag exigem um token criado
com uma conexão (senão 400 ERR_API_REQUIRES_SESSION).
11. O lugar da lista na resposta muda por rota (data, data.campaigns,
data.data) e o bloco pagination também. Confira em "Convenções da API".
12. Em erro, leia o campo error (ex: ERR_MISSING_FIELDS). Se vier field ou
fields, é o campo a corrigir. 201 também é sucesso.
13. bulkIndividual e bulkFastMessage exigem whatsappType (tipo da conexão,
como em listChannels). Sem ele a resposta é 200 com success:true e nada
é enviado.
14. Antes de enviar para clientes, teste com o seu próprio número.
📊 Listagens (GET)
Endpoints de consulta. Use estas rotas para buscar informações da plataforma. Todas retornam JSON.
Lista todas as conexões (canais) da sua conta — WhatsApp, Instagram, Facebook, WebChat, Telegram, etc.
Exemplo
curl --request GET \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/listChannels' \ --header 'Authorization: Bearer SEU_TOKEN'
Lista todas as sessões (instâncias) ativas no seu sistema.
Lista os tickets (atendimentos) com filtros avançados. Suporta paginação.
Query Parameters
| Parâmetro | Tipo | Descrição |
|---|---|---|
pageNumber | int | Número da página (começa em 1). |
status | string obrigatório | Filtra por status: open, pending ou closed. Se você não enviar este parâmetro, a chamada falha com 404 e {"error": "ERR_NO_STATUS_SELECTED"}. |
searchParam | string | Texto para buscar em nome, número ou conteúdo. |
queuesIds | array | IDs das filas para filtrar. |
whatsappIds | array | IDs das conexões WhatsApp. |
selectedUser | int | ID do atendente responsável. |
Exemplo — tickets abertos da fila 3
curl --request GET \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/listTickets?status=open&queuesIds=3&pageNumber=1' \ --header 'Authorization: Bearer SEU_TOKEN'
Lista contatos cadastrados. Suporta filtros por nome, carteira (wallet) e tag.
GET e lê só a query string, por exemplo listContacts?pageNumber=1&searchParam=5511999999999. Filtro enviado no corpo (Body) é ignorado sem erro e a resposta traz a lista sem filtro. A busca encontra o texto em qualquer parte do nome ou do número, então um pedaço do número pode trazer mais de um contato. As tags vêm só com nome e cor; para ter o id da tag, use a busca avançada.Query Parameters
| Parâmetro | Tipo | Descrição |
|---|---|---|
pageNumber | int | Número da página. |
searchParam | string | Busca por nome ou número. |
walletId | int | Filtra contatos da carteira de um vendedor. |
tagId | int | Filtra contatos com determinada tag. |
cep, logradouro, numeroEndereco, complemento, bairro, cidade e estado (vazios vêm null). Para filtrar por endereço, use a busca avançada.Lista todos os usuários (atendentes) cadastrados na sua conta.
Query Parameters
| Parâmetro | Tipo | Descrição |
|---|---|---|
pageNumber | int | Página de resultados. |
searchParam | string | Busca por nome ou e-mail. |
Lista as tags (etiquetas) cadastradas para classificar contatos e tickets.
Query Parameters
| Parâmetro | Tipo | Descrição |
|---|---|---|
isActive | boolean | Filtrar apenas tags ativas (true) ou inativas (false). |
Lista as filas (departamentos) configuradas, como "Vendas", "Suporte", "Financeiro".
Lista as oportunidades (cartões) do funil de vendas (Kanban).
Query Parameters
| Parâmetro | Tipo | Descrição |
|---|---|---|
page | int | Página de resultados. |
limit | int | Itens por página. |
status | string | Status da oportunidade. |
pipelineId | int | ID do pipeline (funil). |
stageId | int | ID do estágio dentro do pipeline. |
Verifica em tempo real se um atendente específico está Online ou Offline.
Query Parameters
| Parâmetro | Tipo | Descrição |
|---|---|---|
userId | intobrigatório | ID do atendente. |
Lista todas as notas internas registradas em um ticket específico.
Query Parameters
| Parâmetro | Tipo | Descrição |
|---|---|---|
ticketId | intobrigatório | ID do ticket. |
Retorna os campos personalizados (extraInfo) de um contato.
Query Parameters
| Parâmetro | Tipo | Descrição |
|---|---|---|
contactId | intobrigatório | ID do contato. |
👤 Contatos (POST)
Endpoints para criar, atualizar e gerenciar contatos. Todos os métodos POST recebem o corpo em JSON com header Content-Type: application/json.
Cria um novo contato no sistema. Os campos de endereço são opcionais; texto acima do limite é cortado, sem erro.
Body
| Campo | Tipo | Descrição |
|---|---|---|
name | stringobrigatório | Nome do contato. |
number | stringobrigatório | Telefone com DDI + DDD (ex: 5511999999999). |
email | stringopcional | E-mail do contato. |
extraInfo | arrayopcional | Campos personalizados [{"name":"...","value":"..."}]. |
cpf | stringopcional | CPF do contato (ex: 012.345.678-90). |
firstName | stringopcional | Primeiro nome. |
lastName | stringopcional | Sobrenome. |
businessName | stringopcional | Nome da empresa do contato. |
birthdayDate | stringopcional | Data de nascimento no formato DD/MM/AAAA (ex: 25/12/1990). Atenção: é o contrário do formato AAAA-MM-DD usado nos filtros de data da API. |
externalKey | stringopcional | Identificador do contato no seu sistema, para você cruzar os dados depois. Não pode se repetir. |
validateNumber | booleanopcional | Padrão true. Veja validateNumber no envio de texto. |
cep | stringopcional | CEP (até 20 caracteres). |
logradouro | stringopcional | Rua (até 255 caracteres). |
numeroEndereco | stringopcional | Número do endereço (até 255). |
complemento | stringopcional | Complemento (até 255). |
bairro | stringopcional | Bairro (até 255). |
cidade | stringopcional | Cidade (até 255). |
estado | stringopcional | Estado (até 100), gravado como veio: GO ou Goiás. A busca por UF acha os dois. |
Exemplo
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/createContact' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "name": "João Silva", "number": "5511999999999", "email": "joao@empresa.com.br" }'
409 ERR_CONTACT_EXISTS com existingContactId: use esse id para seguir com o contato que já existe, sem criar outro. Sem number: 400 ERR_MISSING_NUMBER_OR_BSUID. Token de API sem canal vinculado: 400 ERR_API_REQUIRES_SESSION (crie a API escolhendo uma conexão).Atualiza dados de um contato existente. Só mudam os campos enviados.
Body
| Campo | Tipo | Descrição |
|---|---|---|
number | stringobrigatório | Número do contato que será atualizado. É por ele que o contato é encontrado: esta rota não tem contactId. Número sem cadastro: 404 ERR_CONTACT_NOT_FOUND. |
name | stringopcional | Novo nome. |
email | stringopcional | Novo e-mail. |
cpf | stringopcional | CPF do contato (ex: 012.345.678-90). |
firstName | stringopcional | Primeiro nome. |
lastName | stringopcional | Sobrenome. |
businessName | stringopcional | Nome da empresa do contato. |
birthdayDate | stringopcional | Data de nascimento no formato DD/MM/AAAA (ex: 25/12/1990). Atenção: é o contrário do formato AAAA-MM-DD usado nos filtros de data da API. |
kanban | intopcional | ID da coluna do kanban do contato. |
cep | stringopcional | CEP (até 20 caracteres). "" ou null apaga; campo ausente fica como está. |
logradouro | stringopcional | Rua (até 255 caracteres). |
numeroEndereco | stringopcional | Número do endereço (até 255). |
complemento | stringopcional | Complemento (até 255). |
bairro | stringopcional | Bairro (até 255). |
cidade | stringopcional | Cidade (até 255). |
estado | stringopcional | Estado (até 100), gravado como veio: GO ou Goiás. A busca por UF acha os dois. |
contactId como campo obrigatório. O campo não existe nesta rota: a chamada sem number responde 500. Se a sua integração usa contactId aqui, troque por number.Exemplo: preencher o endereço e depois apagar só o complemento
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/updateContact' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "number": "5511999999999", "cep": "01310-100", "logradouro": "Avenida Paulista", "numeroEndereco": "1000", "bairro": "Bela Vista", "cidade": "São Paulo", "estado": "SP" }' # depois, apagar só o complemento (os outros campos ficam como estão) curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/updateContact' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "number": "5511999999999", "complemento": "" }'
""/null: cada passo conferido na ficha do contato.Move um contato para uma posição (kanban) específica do funil.
Body
| Campo | Tipo | Descrição |
|---|---|---|
contactId | intobrigatório | ID do contato. |
kanban | int|stringobrigatório | ID ou nome do kanban de destino. |
Define a carteira (wallet) de um contato — vincula o contato a um vendedor responsável. Útil para distribuir leads automaticamente.
Body
| Campo | Tipo | Descrição |
|---|---|---|
contactId | intobrigatório | ID do contato. |
walletId | intopcional | ID de um vendedor. Não aceita lista: um array aqui volta com 400 ERR_INVALID_WALLET_ID. |
walletIds | arrayopcional | Lista de IDs de vendedores. Envie walletId ou walletIds. |
"walletIds": [7], ele fica só com o 7. Isso vale também para o walletId. Para acrescentar um vendedor, envie a lista completa; para tirar todos, envie "walletIds": [].Bloqueia ou desbloqueia o chatbot para um contato. Útil para evitar respostas automáticas para contatos VIP.
Body
| Campo | Tipo | Descrição |
|---|---|---|
contactId | intobrigatório | ID do contato. |
blocked | booleanobrigatório | true para bloquear, false para desbloquear. |
Procura contatos repetidos na sua conta e devolve os pares encontrados, sem alterar nada. Útil antes de importar uma base ou ao integrar com um CRM, onde é comum o mesmo cliente entrar duas vezes com números diferentes. O corpo pode ir vazio ({}) ou com os filtros abaixo.
Body
| Campo | Tipo | Descrição |
|---|---|---|
limit | intopcional | Quantos pares devolver, no máximo. Padrão 500. |
matchKinds | arrayopcional | Critérios de busca: "nine_digit_variant" (mesmo número com e sem o nono dígito) e "cross_collision". Sem o campo, usa os dois. |
Resposta
{
"success": true,
"data": {
"pairs": [
{
"matchKind": "cross_collision",
"confidence": "high",
"primaryId": 3,
"duplicateId": 47626,
"primaryNumber": "5511999999999",
"duplicateNumber": "5511988888888",
"primaryName": "Maria Souza",
"duplicateName": "Maria S.",
"ticketsToMove": 0,
"messagesToMove": 5,
"conflictReason": null
}
]
}
}
ticketsToMove e messagesToMove mostram quanto histórico seria transferido se você juntasse o par. confidence indica o quanto o sistema tem certeza de que são a mesma pessoa: confira antes de juntar.
Junta pares de contatos repetidos: o histórico do duplicado passa para o principal. Use os pares devolvidos por findDuplicateContacts.
Body
| Campo | Tipo | Descrição |
|---|---|---|
pairs | arrayobrigatório | Pares a juntar, no formato [{"primaryId":3,"duplicateId":47626}]. Cada par também aceita os números no lugar dos IDs, nos campos primaryNumber e duplicateNumber. Se um número corresponder a mais de um contato, aquele par volta com ERR_NUMBER_AMBIGUOUS e a lista dos candidatos. Até 150 pares por chamada; para mais, divida em lotes. Falha com 400 e {"error":"ERR_PAIRS_REQUIRED"} se o campo estiver ausente, vazio ou não for uma lista. |
200 com success: true
mesmo quando todos os pares falharam. O que vale é
data.summary (total, consolidated,
skipped, errors) e data.results, com um
item por par (index, status, code,
field). Confira summary.errors antes de considerar
a operação concluída.
Desfaz uma junção feita anteriormente, separando os contatos de novo.
Body
| Campo | Tipo | Descrição |
|---|---|---|
duplicateIds | arrayopcional | IDs dos contatos duplicados que foram juntados (o duplicateId usado no mergeContacts). Use este campo ou o mergeLogIds. |
mergeLogIds | arrayopcional | IDs dos registros de junção, como alternativa ao duplicateIds. Até 150 IDs por chamada. As junções são desfeitas da mais recente para a mais antiga. |
duplicateIds (ou mergeLogIds), não ids. Um campo com outro nome é ignorado e a chamada falha com 400 e {"error":"ERR_IDS_REQUIRED"}, como se o corpo estivesse vazio. Com o campo certo, a resposta vem 200 e é avaliada item a item: confira data.summary (total, reverted, errors) e data.results. Um ID sem junção registrada aparece ali com "code": "ERR_MERGE_LOG_NOT_FOUND", e o success: true não quer dizer que algo foi desfeito.Atualiza os campos personalizados (extraInfo) de um contato.
Body
| Campo | Tipo | Descrição |
|---|---|---|
contactId | intobrigatório | ID do contato. |
extraInfo | arrayobrigatório | Array no formato [{"name":"campo","value":"valor"}]. |
Busca paginada com filtros avançados, por nome ou número (searchParam), tag, carteira e bloqueio.
Devolve os dados de cadastro do contato e as tags com o id ("tags": [{"id": 7, "name": "Cliente", "color": "#22c55e"}]), o que a listContacts não traz.
Os filtros vão no corpo (Body), em JSON. Cada contato da resposta traz o endereço (cep, logradouro, numeroEndereco, complemento, bairro, cidade, estado), as tags e as carteiras.
Body
| Campo | Tipo | Descrição |
|---|---|---|
tagId | intopcional | ID de uma tag. |
tagIds | arrayopcional | Lista de IDs de tags: traz os contatos com qualquer uma delas. Envie tagId ou tagIds. |
page | intopcional | Página (padrão: 1). |
limit | intopcional | Itens por página (padrão: 40). |
searchParam | stringopcional | Texto para buscar. |
walletId | intopcional | Filtra pela carteira de um vendedor. |
blocked | booleanopcional | Inclui (false) ou exclui (true) contatos bloqueados. |
addressCidade | stringopcional | Cidade: busca por "contém", sem diferenciar acento nem maiúsculas (goiania acha Goiânia). |
addressBairro | stringopcional | Bairro, com a mesma regra da cidade. |
addressUfs | string ou arrayopcional | Siglas de UF: "SP,RJ" ou ["SP","RJ"]. Acha também o estado gravado por extenso (GO acha Goiás). Sigla que não existe devolve lista vazia, sem erro: confira a sigla. |
Exemplo — buscar todos contatos com a tag "Lead Quente"
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/contacts/search' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "tagId": 42, "page": 1, "limit": 100 }'
Exemplo: contatos de São Paulo e do Rio de Janeiro com a tag 42
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/contacts/search' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "addressUfs": ["SP", "RJ"], "tagId": 42, "limit": 100 }'
meta.addressFilter: true quer dizer que os filtros de endereço foram aplicados.Gera o link de convite do Telegram para um contato que já existe. Quando a pessoa abre o link e toca em Iniciar, o Telegram dela fica ligado a esse contato e você passa a atendê-la por lá. O link vale 7 dias, é de uso único e só o mais recente funciona (gerar de novo cancela o anterior).
| Campo | Tipo | Descrição |
|---|---|---|
contactId | intopcional | ID do contato. Envie contactId ou number. |
number | stringopcional | Telefone do contato, no lugar do contactId. Se o número pertencer a mais de um contato: 422 ERR_NUMBER_AMBIGUOUS com a lista candidates. |
whatsappId | intopcional | ID do bot do Telegram. Dispensável quando o token já é de um canal do Telegram ou quando a conta tem um só bot conectado. |
Exemplo
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/telegramInvite' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "contactId": 123 }'
Resposta
{
"success": true,
"data": {
"link": "https://t.me/seu_bot?start=CODIGO",
"expiresAt": "2026-11-05T11:23:35.842Z",
"contactId": 123,
"whatsappId": 7
}
}
| Erro | Quando acontece |
|---|---|
400 ERR_CONTACT_OR_NUMBER_REQUIRED | Faltou contactId e number. |
404 ERR_CONTACT_NOT_FOUND | Contato não existe (ou foi juntado a outro). |
409 ERR_TELEGRAM_ALREADY_LINKED | O contato já tem Telegram. |
400 ERR_TELEGRAM_INVITE_GROUP | O contato é um grupo. |
400 ERR_TELEGRAM_BOT_REQUIRED | A conta tem mais de um bot: informe whatsappId. |
409 ERR_TELEGRAM_BOT_NOT_FOUND / ERR_TELEGRAM_BOT_OFFLINE | Nenhum bot do Telegram conectado, whatsappId que não é um bot do Telegram da sua conta, ou o bot está desconectado. |
403 ERR_SESSION_NOT_AUTH_TOKEN | O token é de um canal e o whatsappId enviado é de outro. |
424 ERR_TELEGRAM_BOT_UNAVAILABLE | O Telegram não respondeu. Tente de novo. |
403 com o bot de outro canal.📨 Mensagens (POST)
Endpoints para envio de mensagens via WhatsApp através das suas conexões. Suporta texto, arquivos, áudio, localização, e os tipos interativos da API oficial WhatsApp Business (WABA).
Envia uma mensagem de texto para um número WhatsApp.
Body
| Campo | Tipo | Descrição |
|---|---|---|
number | stringobrigatório | Número com DDI + DDD (ex: 5511999999999). |
body | stringobrigatório | Texto da mensagem. |
ticketId | intopcional | Ticket ao qual vincular a mensagem. |
externalKey | stringopcional | Identificador da mensagem no seu sistema. Não pode se repetir. |
isClosed | booleanopcional | true fecha o ticket logo depois do envio. |
validateNumber | booleanopcional | Padrão true: o sistema ajusta o nono dígito de números brasileiros. Com false, usa o número exatamente como você enviou. |
"validateNumber": false e envie o número exatamente como o cliente escreveu para você. O ajuste automático do nono dígito pode gerar um número diferente do que a Meta conhece e abrir um segundo ticket para a mesma pessoa. Em canais que não são WhatsApp, o number é o identificador do canal: IGSID no Instagram, PSID no Messenger e ID do Telegram. Para responder uma conversa que já existe, em qualquer canal, o mais simples é o envio pelo ticket.Exemplo
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "number": "5511999999999", "body": "Olá! Esta é uma mensagem de teste." }'
| Erro comum no envio | O que fazer |
|---|---|
424 ERR_WAPP_CONTACT_UNVERIFIED | O número não tem WhatsApp, ou a consulta ao WhatsApp falhou naquele momento. Confira o número; se estiver certo, tente de novo em alguns segundos. |
400 ERR_CHANNEL_DISCONNECTED | A conexão por QR Code está esperando a leitura do QR. Reconecte o canal no painel. |
400 ERR_INVALID_BODY | body veio como objeto ou lista. Mande texto (número é convertido para texto). |
body e sem arquivo responde 400 ERR_MISSING_BODY_OR_MEDIA.Envia um arquivo (imagem, PDF, áudio, vídeo) a partir de uma URL pública.
Body
| Campo | Tipo | Descrição |
|---|---|---|
number | stringobrigatório | Número de destino. |
mediaUrl | stringobrigatório | URL pública do arquivo. |
body | stringopcional | Legenda / texto que acompanha a mídia. |
Envia uma mensagem para uma conversa que já existe, usando o ID do ticket em vez do número. Funciona em qualquer canal da sua conta (WhatsApp, API Oficial, Instagram, Messenger, Telegram, Webchat e e-mail): o canal é o do próprio ticket. É o caminho mais simples para responder, a partir do seu sistema, uma conversa que chegou por webhook.
Body
| Campo | Tipo | Descrição |
|---|---|---|
ticketId | intobrigatório | ID do ticket (conversa). |
body | stringopcional | Texto da mensagem. Obrigatório quando não há mídia; com mídia, vira a legenda. |
mediaUrl | stringopcional | Endereço público do arquivo (http ou https). Endereços internos são recusados com ERR_BLOCKED_HOST. |
base64Data | stringopcional | Arquivo em base64. Exige mimeType (ex: image/png); aceita fileName. |
media | fileopcional | Arquivo enviado como multipart/form-data, com os outros campos no mesmo formulário. |
externalKey | stringopcional | Chave sua para evitar envio em dobro: repetir a mesma chave em até 2 minutos não envia de novo (veja abaixo). Recomendado. |
reopen | booleanopcional | true reabre o ticket se ele estiver fechado. Sem isso, ticket fechado volta com 409. |
isClosed | booleanopcional | true fecha o ticket depois do envio. |
Use uma fonte de mídia por chamada: media, mediaUrl ou base64Data.
Exemplo
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/sendMessageByTicket' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "ticketId": 1262, "body": "Olá! Recebemos seu pedido.", "externalKey": "pedido-8841-confirmacao" }'
Resposta
{
"success": true,
"data": {
"message": "Message sent successfully",
"ticketId": 1262,
"messageId": null
}
}
Se a mesma externalKey chegar de novo em até 2 minutos, nada é enviado e a resposta é {"success": true, "data": {"idempotent": true, "skipped": true, "ticketId": 1262}}. Isso protege contra mensagem duplicada quando o seu sistema repete a chamada depois de um erro de rede.
Erros
| Código | Quando |
|---|---|
400 ERR_INVALID_TICKET_ID | ticketId ausente ou inválido. |
400 ERR_MISSING_BODY_OR_MEDIA | Sem texto e sem mídia. |
400 ERR_BLOCKED_HOST | mediaUrl aponta para um endereço interno. |
409 ERR_TICKET_CLOSED | Ticket fechado. Envie "reopen": true para reabrir e enviar. |
Envia indicadores de presença (estado) para o WhatsApp do contato — útil para humanizar bots mostrando "digitando..." antes de uma resposta automática.
Body
| Campo | Tipo | Descrição |
|---|---|---|
ticketId | intobrigatório | ID do ticket. |
state | stringobrigatório | typing, paused ou recording. |
typing funciona, e a Meta marca como lida a última mensagem recebida do contato. paused e recording respondem 400 ERR_PRESENCE_NOT_SUPPORTED (paused testado em 29/10/2026).Envia mensagem com até 3 botões interativos via WhatsApp Business API (WABA).
Body
| Campo | Tipo | Descrição |
|---|---|---|
number | stringobrigatório | Número de destino. |
message | stringobrigatório | Texto principal da mensagem. |
button1 | stringobrigatório | Texto do primeiro botão (máx 20 caracteres). |
button2 | stringopcional | Texto do segundo botão. |
button3 | stringopcional | Texto do terceiro botão. |
ticketId | intopcional | Vincular a um ticket existente. |
400 ERR_CHANNEL_WABA_REQUIRED.Envia mensagem com lista interativa (menu suspenso) via WhatsApp Business API (WABA).
Body
| Campo | Tipo | Descrição |
|---|---|---|
number | stringobrigatório | Número de destino. |
header | stringobrigatório | Cabeçalho da lista. |
body | stringobrigatório | Texto principal. |
footer | stringopcional | Rodapé. |
button_text | stringobrigatório | Texto do botão de abertura da lista. |
sections | arrayobrigatório | Seções com itens da lista. |
ticketId | intopcional | Vincular a um ticket existente. |
400 ERR_CHANNEL_WABA_REQUIRED. Se a Meta recusar (número inválido, fora da janela de 24 h, lista fora do formato), a resposta é 400 ERR_WABA_SEND_FAILED com metaCode e a mensagem da Meta: é ela que diz o motivo. Cada item de sections tem title e rows, e cada linha tem id, title e description.🎫 Tickets & Tags
Altera o canal (conexão WhatsApp) de um ticket existente — útil quando você precisa migrar um atendimento de uma conexão para outra.
Body
| Campo | Tipo | Descrição |
|---|---|---|
ticketId | intobrigatório | ID do ticket. |
whatsappId | intobrigatório | ID da nova conexão WhatsApp. |
channel | stringobrigatório | Continua obrigatório só por compatibilidade: o tipo gravado no ticket vem do canal do whatsappId. |
whatsappId precisa ser um canal da sua conta (senão 404 ERR_NO_WAPP_FOUND). A troca fica registrada no histórico do atendimento como mensagem de sistema, que não é enviada ao contato.Adiciona uma nota interna (visível apenas para atendentes) em um ticket.
Body
| Campo | Tipo | Descrição |
|---|---|---|
ticketId | intobrigatório | ID do ticket. |
notes | stringobrigatório | Texto da nota. |
userId | intopcional | ID do atendente que aparece como autor. Precisa ser da sua conta (senão 404 ERR_USER_NOT_FOUND). |
idFront | stringopcional | Chave sua para não duplicar: uma segunda nota com o mesmo idFront é recusada com 409 ERR_NOTE_EXISTS. Útil quando a sua integração pode repetir a chamada. |
201 (não 200). Corpo sem ticketId e sem notes: 400 ERR_MISSING_FIELDS. idFront repetido: 409 ERR_NOTE_EXISTS.Atualiza o conteúdo de uma nota interna existente.
Body
| Campo | Tipo | Descrição |
|---|---|---|
noteId | intobrigatório | ID da nota. |
notes | stringobrigatório | Novo texto. |
Adiciona uma ou mais tags ao contato do ticket sem remover as existentes. Ideal para classificar atendimentos durante automações sem perder histórico.
Body
| Campo | Tipo | Descrição |
|---|---|---|
ticketId | intobrigatório | ID do ticket. |
tagId | intopcional | ID de uma tag. |
tagIds | arrayopcional | Lista de IDs de tags, para adicionar várias de uma vez. Envie tagId ou tagIds. |
tagIds. Um array dentro de tagId volta com 500 (ERR_ADD_TAG ou ERR_REMOVE_TAG), que parece falha do servidor mas é o formato do campo. A tag fica no contato do ticket, então aparece em todas as conversas dele. O token usado precisa estar vinculado a uma conexão; sem isso a resposta é 400 ERR_API_REQUIRES_SESSION.Remove uma ou mais tags específicas do contato do ticket.
Body
| Campo | Tipo | Descrição |
|---|---|---|
ticketId | intobrigatório | ID do ticket. |
tagId | intopcional | ID de uma tag. |
tagIds | arrayopcional | Lista de IDs de tags, para remover várias de uma vez. Envie tagId ou tagIds. |
tagIds. Um array dentro de tagId volta com 500 (ERR_ADD_TAG ou ERR_REMOVE_TAG), que parece falha do servidor mas é o formato do campo. A tag fica no contato do ticket, então aparece em todas as conversas dele. O token usado precisa estar vinculado a uma conexão; sem isso a resposta é 400 ERR_API_REQUIRES_SESSION.👥 Usuários (Atendentes)
Cria um novo usuário (atendente) na sua conta.
Body
| Campo | Tipo | Descrição |
|---|---|---|
name | stringobrigatório | Nome do atendente. |
email | stringobrigatório | E-mail (será o login). |
password | stringobrigatório | Senha inicial. |
profile | stringobrigatório | admin, super ou user. |
Atualiza dados de um usuário existente.
Body
| Campo | Tipo | Descrição |
|---|---|---|
userId | intobrigatório | ID do usuário. |
name | stringopcional | Novo nome. |
email | stringopcional | Novo e-mail. |
📣 Campanhas
Crie e gerencie campanhas de envio programado via API: defina mensagens (com rotação de até 3 variações), data de início, conexão de envio e a lista de contatos. Ideal para integrar disparos a CRMs e automações.
delay com valores adequados e evite enviar a mesma mensagem para muitos destinatários em janelas curtas — envios em massa sem intervalo podem causar restrições no número pelo WhatsApp/Meta. Prefira as 3 variações de mensagem.
Cria uma campanha. Após criar, adicione os contatos e inicie com campaign/start.
Body
| Campo | Tipo | Descrição |
|---|---|---|
name | stringobrigatório | Nome da campanha. |
start | stringobrigatório | Data/hora de início em ISO 8601 (ex: 2026-04-10T10:00:00.000Z). |
message1 | stringobrigatório | Mensagem principal. Aceita placeholder {nome}. |
message2 | stringopcional | Variação 2 (rotação automática entre contatos). |
message3 | stringopcional | Variação 3. |
sessionId | intobrigatório | ID da conexão (canal) que fará os envios — veja Listar Canais. |
delay | stringopcional | Intervalo (segundos) entre envios. |
Exemplo
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/campaign/create' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "name": "Promoção Junho", "start": "2026-06-15T10:00:00.000Z", "message1": "Olá {nome}! Temos uma novidade para você.", "message2": "Oi {nome}, tudo bem? Confira nossa novidade.", "sessionId": 12, "delay": "5" }'
Atualiza uma campanha existente (mesmos campos do create). Só é aceito com a campanha em pending, scheduled, paused ou canceled; em processing ou finished responde 404. O texto vai em message1/message2/message3 e a variável do nome é {{name}}. O status não muda por aqui: use iniciar, pausar, retomar ou cancelar.
Lista as campanhas do tenant com paginação. Retorna status, totais e configuração de cada campanha.
Relatório da campanha: contatos, status de entrega por contato e progresso geral.
Ações de ciclo de vida da campanha. Todas são POST com body vazio ({}).
Ações disponíveis
| Rota | Efeito |
|---|---|
campaign/start/{campaignId} | Inicia o disparo. |
campaign/pause/{campaignId} | Pausa o disparo em andamento. |
campaign/resume/{campaignId} | Retoma uma campanha pausada. |
campaign/cancel/{campaignId} | Cancela definitivamente. |
campaign/skip/{campaignId} | Pula o contato atual da fila. |
campaign/duplicate/{campaignId} | Duplica a campanha (nova cópia em rascunho). |
campaign/delete/{campaignId} | Exclui a campanha. |
Gerencia os contatos de uma campanha. O add recebe um array de contatos no body.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | campaign/contacts/add/{campaignId} | Adiciona contatos (array de {name, number}). |
GET | campaign/contacts/{campaignId} | Lista os contatos da campanha. |
POST | campaign/contacts/remove/{campaignId}/{contactId} | Remove um contato. |
POST | campaign/contacts/removeAll/{campaignId} | Remove todos os contatos. |
Exemplo (add)
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/campaign/contacts/add/123' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '[ { "name": "João", "number": "5511999990001" }, { "name": "Maria", "number": "5511999990002" } ]'
📤 Envio em Lote
Endpoints para disparo direto a múltiplos números, sem criar uma campanha. Os campos min e max definem o intervalo aleatório (em segundos) entre cada envio — essencial para envios saudáveis.
Envia a mesma mensagem para uma lista de números.
Body
| Campo | Tipo | Descrição |
|---|---|---|
whatsappId | intobrigatório | ID da conexão de envio. |
arrayNumbers | arrayobrigatório | Lista de números (DDI+DDD+número). |
message | stringobrigatório | Texto a enviar. |
min / max | intopcional | Intervalo aleatório entre envios, em segundos (ex: 3 a 8). |
Exemplo
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/bulkSendMessage' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "whatsappId": 12, "arrayNumbers": ["5511999990001", "5511999990002"], "message": "Olá, tudo bem?", "min": 3, "max": 8 }'
Envio em massa personalizado por contato: a mensagem usa placeholders e os valores vêm de uma lista CSV (uma linha por destinatário).
Body
| Campo | Tipo | Descrição |
|---|---|---|
whatsappId | intobrigatório | ID da conexão de envio. |
message | stringobrigatório | Mensagem com placeholders, ex: Olá {nome}, seu código é {codigo}. |
dataInput | stringobrigatório | Linhas numero,valor1,valor2 separadas por \n — os valores preenchem os placeholders na ordem. |
min / max | intopcional | Intervalo aleatório entre envios (segundos). |
Exemplo
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/bulkSendMessageWithVariable' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "whatsappId": 12, "message": "Olá {nome}, seu código é {codigo}", "dataInput": "5511999990001,João,ABC123\n5511999990002,Maria,DEF456", "min": 3, "max": 8 }'
Variante do envio em massa que informa o tipo da conexão (whatsappType) — útil quando o tenant tem conexões de tipos diferentes.
Body
| Campo | Tipo | Descrição |
|---|---|---|
whatsappId | intobrigatório | ID da conexão. |
whatsappType | stringobrigatório | Tipo da conexão (conforme retornado em Listar Canais). |
arrayNumbers | arrayobrigatório | Lista de números. |
message | stringobrigatório | Texto a enviar. |
min / max | intopcional | Intervalo aleatório entre envios (segundos). |
whatsapp e baileys, e o whatsappType é obrigatório. Ela não cria atendimento. Para os outros tipos de conexão, use o bulkIndividual número a número.Envio individual pela mesma infraestrutura do lote — aceita externalKey para controle/idempotência do seu lado.
Body
| Campo | Tipo | Descrição |
|---|---|---|
whatsappId | intobrigatório | ID da conexão. |
whatsappType | stringobrigatório | Tipo da conexão, como vem em Listar Canais (ex: whatsapp, baileys, uazapi, waba). Sem ele a resposta é 200 com success: true e nada é enviado. |
number | stringobrigatório | Número de destino. |
message | stringobrigatório | Texto a enviar. |
externalKey | stringopcional | Chave externa para rastrear o envio. |
Exemplo
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/bulkIndividual' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "whatsappId": 246, "whatsappType": "uazapi", "number": "5511999999999", "message": "Olá! Sua encomenda saiu para entrega." }'
whatsappType: 200 com success: true, ticketId: null e nenhuma mensagem enviada. Com ele, em JSON ou em form-data: a mensagem chegou e a resposta trouxe o ticketId do atendimento. Até 29/10/2026 esta página não listava o whatsappType nesta rota. Confira sempre se veio ticketId.Acompanhe os despachos em lote criados pelos endpoints acima.
Rotas
| Método | Rota | Descrição |
|---|---|---|
GET | bulkDispatch/list | Lista despachos (paginação page/limit). |
GET | bulkDispatch/show/{dispatchId} | Detalhe de um despacho (progresso, status). |
POST | bulkDispatch/update/{dispatchId} | Atualiza um despacho — ex: {"status": "cancelled", "cancellationReason": "..."}. |
👥 Grupos WhatsApp
Crie e administre grupos do WhatsApp via API: participantes, administradores, título, descrição, foto e link de convite. Em todas as rotas, whatsappId é o ID da conexão (veja Listar Canais) e groupId é o identificador do grupo (formato 123456789@g.us).
Cria um ou mais grupos e adiciona o número informado como primeiro participante.
Body (exemplo)
{
"whatsappId": 12,
"titles": ["Meu Grupo 1"],
"number": "5511999990001"
}
Ações de administração. Todas recebem whatsappId + groupIds (array) e os campos específicos abaixo.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | group/addParticipant | Adiciona participantes — body extra: participants (array de números). |
POST | group/removeParticipant | Remove participantes — participants. |
POST | group/promote | Promove participantes a admin — participants. |
POST | group/demote | Rebaixa admins a participante — participants. |
POST | group/changeTitle | Altera o título — title. |
POST | group/changeDescription | Altera a descrição — description. |
POST | group/changePicture | Altera a foto — picture: link público da imagem (em JSON) ou o próprio arquivo (em form-data). Testado em 29/10/2026 numa conexão por QR Code: a foto do grupo mudou. A resposta só diz success e não devolve a foto: confira no próprio grupo. |
POST | group/setAdminsOnly | Restringe mensagens a admins — adminsOnly (true/false). |
POST | group/revokeInviteLink | Invalida o link de convite atual. Recebe whatsappId e groupId (um grupo só, não lista). |
POST | group/leave | A conexão sai do grupo. Recebe whatsappId e groupId. Só funciona em conexão da API Oficial; nas outras volta ERR_LEAVE_GROUP_WABA_ONLY. |
Body (exemplo)
{
"whatsappId": 12,
"groupIds": ["123456789@g.us"],
"participants": ["5511999990001"]
}
groupId, status, reason) e, nas conexões por QR Code, participants com o resultado de cada número. Motivos comuns: invite_required (a pessoa só entra por convite), already_in_group, not_on_whatsapp, not_in_group; no grupo, not_admin (a conexão não é administradora) e session_not_connected. Se todos os números forem recusados, vem ERR_GROUP_PARTICIPANTS_REJECTED; lista vazia, ERR_GROUP_PARTICIPANTS_REQUIRED.Consultas de grupos da conexão.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | group/list | Lista os grupos — body: {whatsappId}. |
POST | group/listParticipants | Participantes de grupos — {whatsappId, groupIds}. |
POST | group/showById | Detalhe de um grupo — {whatsappId, groupId}. |
POST | group/getInviteLink | Link de convite — {whatsappId, groupId}. |
POST | listGroupInfo | Listagem geral com participantes — {listGroups: true, listParticipants: true} (opcional groupId). |
Envia mensagens para um grupo. No campo number, informe o ID numérico do grupo (sem o sufixo @g.us).
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | /v2/api/external/{apiId}/group | Texto para grupo — body: {body, number, externalKey, isClosed}. |
POST | /v2/api/external/{apiId}/groupMediaUrl | Arquivo via URL — body: {mediaUrl, body, number, externalKey, isClosed}. |
Body (exemplo)
{
"body": "A mensagem desejada",
"number": "123456789015189153",
"externalKey": "SUA_CHAVE_EXTERNA",
"isClosed": false
}
📨 Mensagens — Recursos Adicionais
Complementos aos endpoints de envio de texto e arquivo: áudio como mensagem de voz, arquivo em base64, localização, cartão de contato (vCard), busca e consulta de mensagens.
Envia um áudio como mensagem de voz (PTT) a partir de uma URL pública.
Body (exemplo)
{
"audio": "https://exemplo.com/audio.ogg",
"number": "5511999999999",
"externalKey": "SUA_CHAVE_EXTERNA",
"isClosed": false
}
Envia arquivo codificado em base64 — útil quando o arquivo não tem URL pública.
Body (exemplo)
{
"body": "A mensagem desejada",
"number": "5511999999999",
"base64Data": "iVBORw0KGgoAAAANSUhEUgAA...",
"mimeType": "image/png",
"fileName": "exemplo_imagem",
"isClosed": false
}
Envio de texto via GET (parâmetros na URL) — para integrações que só conseguem disparar GET. Informe body, number, externalKey, bearertoken e opcional isClosed.
Envia uma localização (pin no mapa) com nome e endereço. O destino vem de number e o ticketId é obrigatório: é o atendimento em que a mensagem fica registrada. Ticket de outra conta: 404 ERR_TICKET_NOT_FOUND.
Body (exemplo)
{
"number": "5511999990001",
"latitude": -23.5505,
"longitude": -46.6333,
"name": "São Paulo",
"address": "Av. Paulista, 1000",
"ticketId": 1262,
"externalKey": "SUA_CHAVE_EXTERNA"
}
ticketId: 400 ERR_MISSING_TICKET e nada é enviado. Com o ticket, a localização chega normalmente. Até 29/10/2026 o exemplo desta página trazia "ticketId": null, que não funciona.Envia um cartão de contato (vCard). O ticketId é obrigatório, como na localização. Dentro de contact, os campos fullName, wuid e phoneNumber são obrigatórios; organization e email são opcionais.
Body (exemplo)
{
"number": "5511999990001",
"contact": [
{
"fullName": "João Silva",
"wuid": "5511999990002@s.whatsapp.net",
"phoneNumber": "5511999990002"
}
],
"ticketId": 1262,
"externalKey": "SUA_CHAVE_EXTERNA"
}
contact aceito como lista (exemplo acima) e como objeto único ("contact": {"fullName": "...", "wuid": "...", "phoneNumber": "..."}). Sem ticketId: 400 ERR_MISSING_TICKET.Consulta de mensagens.
Rotas
| Método | Rota | Descrição |
|---|---|---|
GET | searchMessages?ticketId=...&searchParam=...&page=1&limit=20 | Busca textual nas mensagens de um ticket. |
GET | getMessageByMessageId?messageId=... | Recupera uma mensagem pelo ID do WhatsApp. |
🧩 Mensagens Interativas
Botões, listas, enquetes e templates ricos. Os recursos disponíveis dependem do tipo da conexão do ticket. Todos os endpoints recebem ticketId e respondem dentro da conversa existente.
Conexões padrão (não-oficiais).
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | sendInteractive/baileys/quickReply | Botões de resposta rápida — {ticketId, body:{text}, footer:{text}, buttons:[{display_text,id}]}. |
POST | sendInteractive/baileys/singleSelect | Lista de seleção única — {ticketId, body, footer, list:{title, sections:[{title, rows:[{id,title,description}]}]}}. |
POST | sendInteractive/baileys/pixButton | Botão PIX — {ticketId, pixType, pixKey, pixName, bodyText}. |
POST | sendInteractive/baileys/ctaCopy | Botão copiar código — {ticketId, body, footer, displayText, copyCode}. |
POST | sendInteractive/baileys/ctaUrl | Botão abrir URL — {ticketId, body, footer, displayText, url}. |
POST | sendInteractive/baileys/ctaCall | Botão ligar — {ticketId, body, footer, displayText, phoneNumber}. |
Body (exemplo)
{
"ticketId": 1262,
"body": { "text": "Escolha uma opção:" },
"footer": { "text": "Rodapé opcional" },
"buttons": [
{ "display_text": "Opção 1", "id": "op1" },
{ "display_text": "Opção 2", "id": "op2" }
]
}
Conexões do tipo uazapi.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | sendInteractive/uazapi/button | Botões — {ticketId, text, choices:[...], footerText, imageButton}. |
POST | sendInteractive/uazapi/list | Lista — {ticketId, text, choices, listButton, footerText}. |
POST | sendInteractive/uazapi/poll | Enquete — {ticketId, text, choices, selectableCount}. |
POST | sendInteractive/uazapi/carousel | Carrossel de cards — {ticketId, text, carousel:[{text,image,buttons:[{text,type}]}]}. |
POST | sendInteractive/uazapi/pixButton | Botão PIX — {ticketId, pixType, pixKey, pixName}. |
POST | sendInteractive/uazapi/locationButton | Solicitar localização — {ticketId, text}. |
POST | sendInteractive/uazapi/requestPayment | Solicitação de pagamento — {ticketId, amount, title, text, footer, itemName, invoiceNumber, pixType, pixKey, pixName}. Obrigatórios: ticketId e amount. Aceita também boleto (boletoCode), link de pagamento (paymentLink) e anexo (fileUrl, fileName). |
Body (exemplo)
{
"ticketId": 1262,
"text": "Qual sua preferência?",
"choices": ["Opção A", "Opção B", "Opção C"],
"selectableCount": 1
}
Conexões Instagram Direct.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | sendInteractive/instagram/quickReply | Respostas rápidas — {ticketId, message, quickReplies:[{content_type,title,payload}]}. |
POST | sendInteractive/instagram/buttonTemplate | Botões — {ticketId, message, buttons:[{type,title,payload}]}. |
POST | sendInteractive/instagram/genericTemplate | Cards — {ticketId, elements:[{title,subtitle,image_url,buttons}]}. |
POST | instagram/iceBreakers | Perguntas iniciais (get/set/delete) — {action, iceBreakers:[{question,payload}]}. |
POST | instagram/persistentMenu | Menu persistente (get/set/delete) — {action, composerInputDisabled, menuItems}. |
Conexões Facebook Messenger.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | sendInteractive/messenger/quickReply | Respostas rápidas — {ticketId, message, quickReplies}. |
POST | sendInteractive/messenger/buttonTemplate | Botões — {ticketId, message, buttons} (suporta web_url). |
POST | sendInteractive/messenger/genericTemplate | Cards — {ticketId, elements}. |
POST | sendInteractive/messenger/mediaTemplate | Mídia + botões — {ticketId, mediaType, mediaUrl, buttons}. |
POST | sendInteractive/messenger/receiptTemplate | Recibo de compra — {ticketId, receipt:{recipient_name, order_number, currency, summary, elements}}. |
POST | sendInteractive/messenger/messageTag | Mensagem fora da janela 24h com tag — {ticketId, message, tag} (ex: POST_PURCHASE_UPDATE). |
POST | sendInteractive/messenger/customerFeedback | Pesquisa NPS/CSAT — {ticketId, title, subtitle, business_privacy_url, expires_in_days, feedback_screens}. |
POST | messenger/greeting | Saudação da página (get/set/delete) — {action, greetings:[{locale,text}]}. |
POST | messenger/personas | Personas de atendente (list/create/delete) — {action, name, profilePictureUrl}. |
📋 Templates WABA (API Oficial)
Na API Oficial do WhatsApp, a primeira mensagem para um contato, ou qualquer mensagem depois de 24 horas sem resposta dele, só pode ser um modelo (template) aprovado pela Meta.
Envia um modelo aprovado, com ou sem variáveis. Cria (ou usa) o atendimento do contato no painel.
Qual rota usar
| Rota | Quando |
|---|---|
template | Use esta. Serve para modelo sem variáveis, com variáveis no corpo, com botão de link e com imagem, vídeo ou documento no cabeçalho. |
templateBody | Aceita o mesmo formato de corpo da rota template. |
templateMarketingBody | Mesmo corpo da rota template, com o caminho escolhido pela categoria do modelo: modelo de Marketing sai pela Marketing Messages API da Meta quando a conta já aceitou os termos dela (senão, pelo envio comum); Utilidade e Autenticação saem pelo envio comum, então a rota também aceita modelo de Utilidade. Testado em 30/10/2026: o modelo de Marketing foi cobrado pela Meta na categoria da Marketing Messages API (marketing_lite) e o de Utilidade foi aceito pela mesma rota. |
Body
| Campo | Tipo | Descrição |
|---|---|---|
number | stringobrigatório | Número do contato só com dígitos: DDI + DDD + número (ex.: 5511999999999). |
templateData | objectobrigatório | O objeto completo no formato da Meta: messaging_product, type e template. O campo to é opcional: o sistema usa o number. |
isClosed | booleanopcional | true fecha o atendimento logo depois do envio (aviso automático, sem conversa). false deixa aberto. |
validateNumber | booleanopcional | Padrão true: o sistema ajusta o número (9º dígito). Com false, usa o número exatamente como enviado. Recomendado false na API Oficial: evita contato e atendimento em dobro para a mesma pessoa. |
Dentro de template
| Campo | Descrição |
|---|---|
name | Nome do modelo exatamente como aprovado na Meta (minúsculas e _). |
language.code | O idioma em que o modelo foi aprovado, ex.: pt_BR. Com outro idioma, a Meta recusa como se o modelo não existisse. |
components | Só quando o modelo tem variáveis, botão de link com final variável ou mídia no cabeçalho. Os valores vão na ordem das variáveis ({{1}}, {{2}}...) e na mesma quantidade. Modelo sem variáveis: não envie components, nem vazio. |
Exemplo 1: modelo sem variáveis
{
"number": "5511999999999",
"isClosed": false,
"validateNumber": false,
"templateData": {
"messaging_product": "whatsapp",
"type": "template",
"template": {
"name": "boas_vindas",
"language": { "code": "pt_BR" }
}
}
}
Exemplo 2: variáveis no corpo ({{1}} = nome, {{2}} = valor) e botão de link com final variável
{
"number": "5511999999999",
"isClosed": true,
"validateNumber": false,
"templateData": {
"messaging_product": "whatsapp",
"type": "template",
"template": {
"name": "fatura_disponivel",
"language": { "code": "pt_BR" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Maria" },
{ "type": "text", "text": "R$ 150,00" }
]
},
{
"type": "button",
"sub_type": "url",
"index": "0",
"parameters": [ { "type": "text", "text": "abc123" } ]
}
]
}
}
}
Exemplo 3: vídeo no cabeçalho, variáveis no corpo e botão de link com final variável
{
"number": "5511999999999",
"isClosed": true,
"validateNumber": false,
"templateData": {
"messaging_product": "whatsapp",
"type": "template",
"template": {
"name": "reuniao_confirmada",
"language": { "code": "pt_BR" },
"components": [
{
"type": "header",
"parameters": [
{ "type": "video", "video": { "link": "https://seusite.com.br/video.mp4" } }
]
},
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Maria" },
{ "type": "text", "text": "29/10" },
{ "type": "text", "text": "19:30" }
]
},
{
"type": "button",
"sub_type": "url",
"index": "0",
"parameters": [ { "type": "text", "text": "abc123" } ]
}
]
}
}
}
O cabeçalho vai em components, antes do body. O modelo aprovado com mídia no cabeçalho pede a mídia em todo envio: sem ela, a Meta recusa com (#132012). Para imagem ou documento, troque o item de parameters do cabeçalho por { "type": "image", "image": { "link": "https://..." } } ou { "type": "document", "document": { "link": "https://...", "filename": "proposta.pdf" } }.
Quem baixa o arquivo é a Meta, pelo link, depois que a API já respondeu. O endereço precisa ser público, abrir o arquivo direto (página do YouTube ou do Google Drive não serve) e aceitar o acesso dos servidores da Meta: CDN ou proteção contra robôs no seu site podem barrar o download. Limites da Meta: vídeo MP4 com H.264 e áudio AAC, até 16 MB; imagem JPG ou PNG, até 5 MB; documento até 100 MB.
Resposta de sucesso
{
"success": true,
"data": {
"message": "Message sent successfully",
"ticketId": 4521
}
}
A resposta traz o ticketId do atendimento, não o código da mensagem na Meta. Confira sempre o success: há falhas que voltam com HTTP 200 e "success": false.
Erros mais comuns
| Resposta | O que conferir |
|---|---|
400 ERR_SEND_UPSTREAM | A Meta recusou o envio. O motivo vem no error, com o código da Meta entre parênteses: (#132012) é parâmetro em formato diferente do modelo (por exemplo, cabeçalho de vídeo sem o vídeo); (#131008) é variável vazia ou faltando. Versões anteriores respondiam 500 ERR_SEND_TEMPLATE, sem o motivo: trate os dois. Confira, nesta ordem: (1) a chave está ligada à conexão da API Oficial; (2) templateData tem messaging_product, type e template (só name e language soltos não funcionam); (3) name e language.code iguais aos do modelo aprovado; (4) a quantidade de variáveis bate com o modelo; (5) o modelo está aprovado, e não pausado ou em análise. Se tudo confere, fale com o suporte informando o número e a hora do envio. |
200 e a mensagem não chega | Com mídia no cabeçalho, a Meta baixa o arquivo depois de aceitar o envio. Se o download falha (erro 131053 da Meta), ela descarta a mensagem e a resposta da API não muda. Abra o link numa janela anônima, confira o formato e o tamanho, e desligue a CDN ou a proteção contra robôs para o endereço do arquivo. Se tudo confere, fale com o suporte informando o número e a hora do envio. |
number, 400 ERR_MISSING_NUMBER_OR_BSUID; templateData que não é objeto, 400 ERR_INVALID_TEMPLATE_DATA (texto com JSON também é aceito); components que não é lista, 400 ERR_INVALID_TEMPLATE_COMPONENTS; objeto ou lista no text de um parâmetro, 400 ERR_INVALID_TEMPLATE_PARAMETER (número vira texto).🎫 Tickets — Gestão Completa
Criação de tickets, consulta por número ou ID, atualização de fila/status/integrações, tags por contato, pausa e compartilhamento.
Cria um ticket com mensagem inicial. userId (o atendente do ticket) é obrigatório: sem ele, 400 ERR_MISSING_FIELDS com "fields": ["userId"]; usuário de outra conta, 404 ERR_USER_NOT_FOUND. Para canais de e-mail (webmail), use email em vez de number e informe o channelId do canal webmail. Campos opcionais: name/firstName/lastName (criação do contato), kanbanId, chatFlowId, queueId, reasonId, value.
Body (exemplo)
{
"body": "A mensagem desejada",
"number": "5511999999999",
"externalKey": "SUA_CHAVE_EXTERNA",
"userId": 3,
"status": "pending"
}
userId falha antes de enviar qualquer mensagem.Consultas de tickets e mensagens.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | showticket | Ticket ativo do contato — {number}. |
POST | showallticket | Todos os tickets do contato — {number}. |
POST | showticketchatbot | Ticket em atendimento por chatbot — {number}. |
POST | showTicketById | Ticket por ID — {ticketId}. |
POST | showAllMessages | Todas as mensagens de um ticket — {ticket} (também aceita ticketId). Sem ele: 400 ERR_MISSING_TICKET. |
showAllMessages traz também mensagens de sistema, que nunca foram enviadas ao contato: notas internas (mediaType notes ou callNotes) e marcas de transferência (mediaType transfer; nas novas, dataJson traz origem, destino e autor). Se você exporta a conversa ou manda para uma IA resumir, filtre por mediaType para não misturar nota interna com o que o cliente leu.Atualizações do ticket.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | updateticketinfo | Status, fila e integrações — {ticketId, userId, status, queueId, typebotStatus, chatgptStatus, dialogflowStatus, difyStatus, n8nStatus, chatFlowId}. |
POST | updatequeue | Altera a fila — {ticketId, queueId}. Só esses dois campos são lidos; null tira a fila. Fila de outra conta: 404 ERR_QUEUE_NOT_FOUND. |
POST | updatetag | Substitui todas as tags do contato pela tag informada: {ticketId, tag}. Para acrescentar sem apagar as outras, use addTag. |
updatetag apaga as outras tags. Num teste, um contato com 5 tags ficou só com a tag enviada, e o efeito vale para todos os tickets desse contato. Esta página dizia antes "define a tag principal", o que não descrevia isso.Validação (updateticketinfo) | Resposta |
|---|---|
ticketId que não é número | 400 ERR_INVALID_TICKET_ID |
status fora de open, pending, closed | 400 ERR_INVALID_STATUS |
Campos *Status (typebotStatus, chatgptStatus...) com valor que não seja true/false, 1/0 ou enabled/disabled | 400 ERR_INVALID_FIELD com field |
queueId, userId ou chatFlowId de outra conta | 404 ERR_QUEUE_NOT_FOUND, ERR_USER_NOT_FOUND ou ERR_CHATFLOW_NOT_FOUND |
mediaType transfer), que não é enviada ao contato.status e typebotStatus inválidos no updateticketinfo, ticketId que não é número e a troca de todas as tags no updatetag, fila inexistente no updatequeue (as tags do contato de teste foram restauradas depois).Tags por contato (sem precisar de ticket). Localize por contactId ou number; aceita tagId ou tagIds. O addTagContact mantém as tags existentes.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | addTagContact | Adiciona tag(s) ao contato. |
POST | removeTagContact | Remove tag(s) do contato. |
Body (exemplo)
{
"contactId": 123,
"tagId": 1
}
Pausa de atendimento com motivo e histórico.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | ticket/pause/start/{ticketId} | Inicia pausa — body: {pauseReason}. |
POST | ticket/pause/end/{ticketId} | Encerra a pausa. |
GET | ticket/pause/logs/{ticketId} | Histórico de pausas do ticket. |
409 ERR_TICKET_ALREADY_PAUSED. Encerrar sem pausa ativa: 409 ERR_TICKET_NOT_PAUSED. Ticket inexistente: 404 ERR_NO_TICKET_FOUND.Compartilhamento e avaliações.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | ticket/share | Compartilha o ticket com outros usuários: {ticketId, userIdArray: [2, 5]}. Cada ticket aceita um compartilhamento só: repetir responde 400. |
GET | ticket/share/{ticketId} | Consulta o compartilhamento. |
GET | listTicketEvaluations?page=1&limit=20 | Lista avaliações de atendimento. Filtros: startDate, endDate (AAAA-MM-DD), evaluation e search. |
POST | sendEvaluation | Envia a pesquisa de avaliação no ticket. Recebe ticketId; aceita também body, externalKey e force. |
🏗️ CRM — Pipelines, Oportunidades e Cadastros
Estruture o funil de vendas via API: pipelines e estágios, oportunidades vinculadas a contatos, e os cadastros de apoio (kanban, tags, motivos de encerramento e filas).
CRUD de pipelines (funis) e estágios.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | pipeline/create | Cria — {name}. O pipeline só tem nome: description é ignorado. |
GET | pipeline/list?page=1&limit=20 | Lista. |
GET | pipeline/show/{id} | Detalhe. |
POST | pipeline/update/{id} | Atualiza — {name}. |
POST | pipeline/delete/{id} | Exclui. Só funciona com o pipeline vazio (sem etapas nem oportunidades); senão responde 500. |
POST | stage/create | Cria estágio — {name, pipelineId, order, color}. Opcionais: notifyUserId e notifyQueueId (quem é avisado quando uma oportunidade entra na etapa). |
GET | stage/list?pipelineId=... | Lista estágios do pipeline. |
GET | stage/show/{id} | Detalhe do estágio. |
POST | stage/update/{id} | Atualiza estágio. |
POST | stage/delete/{id} | Exclui estágio. Só funciona sem oportunidades nele (mova-as antes); senão responde 500. |
description: o campo foi ignorado e o pipeline nasceu só com o nome.Oportunidades de venda. status: open, win ou lose. Se o contato não existir, é criado a partir de number/contactName/email. Veja também Listar Oportunidades.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | createOpportunity | Cria oportunidade. |
POST | updateOpportunity | Atualiza — {opportunityId, ...}. |
POST | deleteOpportunity | Exclui — {opportunityId}. |
Body (exemplo)
{
"number": "5511999990001",
"contactName": "Nome do Contato",
"email": "contato@email.com",
"name": "Proposta Empresa X",
"value": 10000.00,
"status": "open",
"pipelineId": 16,
"stageId": 7,
"responsibleId": 1,
"closingForecast": "2026-12-31",
"description": "Descrição da oportunidade"
}
number, name (até 255 caracteres), pipelineId, stageId (uma etapa desse pipeline) e responsibleId. closingForecast aceita AAAA-MM-DD, DD/MM/AAAA ou data e hora com fuso. Erros: 400 ERR_MISSING_FIELDS (com fields), ERR_INVALID_OPPORTUNITY_REFERENCE (pipeline, etapa ou responsável de outra conta, com field) e ERR_STAGE_NOT_IN_PIPELINE. No updateOpportunity só opportunityId é obrigatório.Cadastros de apoio: tags, colunas de kanban, motivos de encerramento e filas.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | createTag | Cria tag — {tag, color, isActive} (tag e color obrigatórios). Nome repetido: 409 ERR_TAG_DUPLICATED. |
POST | updateTagData/{id} | Atualiza tag — {tag, color}. |
POST | deleteTag/{id} | Exclui tag. |
POST | createKanban | Cria coluna kanban — {name, position}. |
GET | listKanban | Lista colunas. |
POST | updateKanban/{id} | Atualiza coluna. |
POST | deleteKanban/{id} | Exclui coluna. |
POST | createReason | Cria motivo — {name}. |
GET | listReasons | Lista motivos. |
POST | updateReason/{id} | Atualiza motivo. |
POST | deleteReason/{id} | Exclui motivo. |
POST | createQueueData | Cria fila — {queue, isActive}. Opcionais: businessHours e messageBusinessHours (mensagem fora do horário). A fila nasce sem cor. |
POST | updateQueueData/{id} | Atualiza fila. Atenção: zera a cor da fila e refaz o vínculo da fila com o usuário dono do token. Para manter a cor, edite pelo painel. |
POST | deleteQueueData/{id} | Exclui fila. |
tag (não name), e o da fila no campo queue.📅 Agendamentos e Lembretes
Agende compromissos vinculados a contatos e configure lembretes automáticos por WhatsApp antes de cada evento.
Agendamentos ligados a contatos. Obrigatórios: title (até 255 caracteres) e startAt. status: pending (padrão), confirmed, cancelled, completed ou no_show.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | appointment/create | Cria. |
GET | appointment/list?page=1&limit=20&status=pending | Lista em ordem de início. Filtros: status, search, startFrom e startTo (mesmos formatos de data do create). |
GET | appointment/show/{id} | Detalhe. |
POST | appointment/update/{id} | Atualiza só os campos enviados. Aceita também checkInStatus, location e meetingLink. |
POST | appointment/delete/{id} | Exclui. |
Body (exemplo)
{
"title": "Reunião de Vendas",
"description": "Reunião sobre proposta comercial",
"contactId": 123,
"contactName": "João Silva",
"contactPhone": "5511999999999",
"whatsappId": 12,
"userId": 3,
"startAt": "15/06/2026 14:00",
"endAt": "2026-06-15T15:00:00-03:00",
"status": "pending",
"notes": "Levar proposta impressa"
}
| Campo | Tipo | Descrição |
|---|---|---|
startAt | stringobrigatório | Início. Aceita 2026-06-15, 2026-06-15 14:00, 2026-06-15T14:00:00-03:00 ou 15/06/2026 14:00. Com barra é sempre dia/mês/ano. Sem fuso, vale o horário de Brasília. Só a data = 00:00. Número (timestamp) ou outro formato: 400 ERR_INVALID_START_AT. |
endAt | stringopcional | Fim, nos mesmos formatos. Antes do início: 400 ERR_END_AT_BEFORE_START_AT. No update, null apaga o fim. |
userId | intopcional | Atendente responsável. Sem ele, o agendamento nasce sem atendente. |
bookingProfessionalId | intopcional | Profissional da página de agendamento. |
contactId | intopcional | Contato. contactId, whatsappId, userId e bookingProfessionalId precisam ser da sua conta (senão 404). |
checkInStatus | stringopcional | Só no update. none, confirmed, on_the_way ou no_show. Outro valor: 400 ERR_INVALID_FIELD com field. |
15/11/2026 14:00 gravou 17:00 UTC (horário de Brasília). checkInStatus enviado no create foi ignorado (nasceu none); no update funcionou. Fim antes do início, timestamp numérico, check-in inválido e filtro de data inválido responderam com os códigos da tabela.Regras de lembrete automático: a mensagem é enviada N horas antes do agendamento, pela conexão indicada.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | scheduleReminder/create | Cria regra. |
GET | scheduleReminder/list | Lista regras. |
POST | scheduleReminder/update/{id} | Atualiza. |
POST | scheduleReminder/toggle/{id} | Ativa/desativa. |
POST | scheduleReminder/delete/{id} | Exclui. |
Body (exemplo)
{
"name": "Lembrete 24h antes",
"description": "Envia mensagem ao contato 24h antes do agendamento",
"hoursBeforeEvent": 24,
"messageType": "message",
"messageContent": "Olá {nome}, lembrete da sua reunião amanhã!",
"whatsappId": 12,
"active": true
}
hoursBeforeEvent horas antes de cada agendamento. Obrigatórios: hoursBeforeEvent (número inteiro) e messageType (message ou waba_template); faltando, 400 ERR_MISSING_FIELDS. whatsappId de outra conta: 404 ERR_NO_WAPP_FOUND. No update, campo com outro nome é descartado sem erro.📊 Dashboard e Relatórios
Indicadores de atendimento para alimentar BI e relatórios externos. Todos os endpoints são GET e aceitam startDate e endDate (formato AAAA-MM-DD).
Indicadores disponíveis:
Rotas
| Método | Rota | Descrição |
|---|---|---|
GET | dash/ticketsAndTimes | Totais de tickets e tempos médios (espera/atendimento). |
GET | dash/ticketsStatus | Distribuição por status. |
GET | dash/ticketsChannels | Distribuição por canal. |
GET | dash/ticketsQueue | Distribuição por fila. |
GET | dash/ticketsPerUser | Volume por atendente. |
GET | dash/ticketsUser | Detalhe por atendente. |
GET | dash/ticketsReasons | Distribuição por motivo de encerramento. |
GET | dash/ticketsEvolution | Evolução diária de tickets. |
GET | dash/ticketsEvolutionByValue | Evolução por valor. |
GET | dash/ticketsEvolutionChannelsName | Evolução diária por canal. |
&isGroup=true (testado em 29/10/2026: os números mudam por completo).🔌 Canais e Sessões
Gerencie as conexões WhatsApp do tenant via API: criar, iniciar, obter QR Code e consultar canais. Complementa Listar Canais e Listar Sessões.
Ciclo de vida da sessão (conexão).
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | createtSession | Cria sessão — {name, status, type}. Atenção: a rota é createtSession mesmo (grafia da plataforma). |
POST | startSession | Inicia — {whatsappId}. |
POST | qrCodeSession | Obtém o QR Code atual — {whatsappId}. |
POST | requestNewQrCodeSession | Força novo QR Code — {whatsappId}. |
POST | deleteSession | Exclui a sessão — {whatsappId}. |
POST | showChannel | Consulta canal pelo número — {number}. |
POST | showChannelById | Consulta canal por ID — {id}. |
GET | getAllSessionApis | Lista as configurações de API do tenant. |
🗂️ Utilitários
Galeria de arquivos, tarefas (to-do), logs de chamadas, consulta de contato por número e listagens auxiliares.
Consulta um contato pelo número de WhatsApp (retorna dados completos, incluindo tags e carteiras).
Body (exemplo)
{
"number": "5511999999999"
}
Galeria de arquivos do tenant. O upload é multipart/form-data (campo de arquivo + description).
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | gallery/upload | Envia até 10 arquivos (multipart, campo files, limite de 500 MB). Opcionais: description (vale para todos) e folderId (pasta). |
GET | gallery/list?pageNumber=1&fileType=image | Lista arquivos, 20 por página. Filtros: fileType, searchParam e folderId (none = só os sem pasta; o id = só os da pasta). |
GET | gallery/folders | Lista as pastas em ordem alfabética, com a quantidade de arquivos de cada uma. |
POST | gallery/delete/{id} | Exclui arquivo. |
Resposta do gallery/folders
{
"success": true,
"data": {
"available": true,
"folders": [{ "id": 1, "name": "Produtos", "count": 12 }],
"unfiledCount": 30,
"totalCount": 42
}
}
unfiledCount = arquivos sem pasta; totalCount = todos. Pasta inexistente ou de outra conta: 400 ERR_GALLERY_FOLDER_NOT_FOUND. Cota da galeria estourada no upload: 413 ERR_GALLERY_QUOTA_EXCEEDED, e nenhum arquivo é salvo. As pastas são criadas pelo painel.gallery/folders, a lista com folderId=none (a resposta traz folderFilter) e a pasta inexistente.Tarefas (to-do) por usuário. priority: low/medium/high; status: pending/finished.
Rotas
| Método | Rota | Descrição |
|---|---|---|
POST | todo/create | Cria — {name, description, owner, ownerId, status, priority, limitDate, reminderMinutes, contactId, ticketId}. |
GET | todo/list | Lista. |
POST | todo/update/{id} | Atualiza só os campos enviados, ex: {status: finished}. Prazo novo ainda não vencido volta delayed para pending. |
POST | todo/delete/{id} | Exclui. |
GET | todo/logs/{userId} | Histórico de alterações por usuário. |
| Campo | Tipo | Descrição |
|---|---|---|
limitDate | stringopcional | Prazo. 2026-06-15 = tarefa do dia (atrasa quando o dia acaba). 2026-06-15 14:30 = tarefa com horário (sem fuso, horário de Brasília). Não use barra: 02/03/2027 é lido como mês/dia e vira 3 de fevereiro. Data ilegível: 400 ERR_INVALID_FIELD. |
reminderMinutes | intopcional | Lembrete ao responsável: 0, 10, 30 ou 60 minutos antes. Só vale para tarefa com horário e com ownerId. Outro valor: 400 ERR_INVALID_FIELD. |
ownerId | intopcional | Responsável (id de usuário, veja listUsers): recebe o lembrete. Id que não é da sua conta cria a tarefa sem responsável e a resposta traz "ownerIgnored": true. Confira esse campo. |
contactId | intopcional | Liga a tarefa a um contato. Com ticketId, o ticket precisa ser do mesmo contato. |
ticketId | intopcional | Liga a tarefa a um atendimento (liga também o contato dele). |
limitHasTime e reminderAt), lembrete inválido, ownerIgnored com usuário inexistente e a data com barra lida como mês/dia.Envia as respostas de um formulário da sua conta, como se a pessoa tivesse preenchido a página do formulário: acha ou cria o contato, aplica as etiquetas, abre o atendimento (ou entra no que já está aberto) e manda a confirmação, se o formulário tiver. Útil para levar ao Pro+ um formulário do seu site ou de outro sistema. Não passa pelas travas contra robôs da página pública.
| Campo | Tipo | Descrição |
|---|---|---|
formId | intopcional | Id do formulário (aba Compartilhar do formulário). Envie formId ou slug; com os dois, vale o formId. |
slug | stringopcional | O endereço do formulário: o que vem depois de /f/ no link. |
answers | objectobrigatório | Respostas pela chave de cada campo (mostrada na aba Compartilhar). Telefone com + e o código do país; lista = id da opção; múltipla escolha = lista de ids; caixa de confirmação = true; data em AAAA-MM-DD. |
ref | stringopcional | Página de onde veio o envio (guardada sem a query). |
Exemplo
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/formSubmit' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "formId": 12, "answers": { "f_nome": "Maria Souza", "f_telefone": "+5511999998888", "f_email": "maria@exemplo.com" }, "ref": "https://www.seusite.com.br/contato" }'
Resposta
{ "ok": true, "submissionId": 87, "status": "processed", "ticketId": 1262, "contactId": 123, "errorCode": null }
status: processed = atendimento aberto ou atualizado; failed = o envio ficou em Respostas sem atendimento (errorCode diz o motivo) e pode ser refeito pelo painel; skipped = contato bloqueado.| Erro | Quando acontece |
|---|---|
400 ERR_FORM_ID_OR_SLUG_REQUIRED | Faltou formId e slug. |
404 ERR_FORM_NOT_FOUND | Formulário não existe, está desativado, é de outra conta ou não tem canal ativo. |
400 ERR_FORM_INVALID | answers fora do formato, ou campo inválido: details.fields traz um código por campo (required, invalidPhone, invalidEmail, invalidOption...). |
400 ERR_FORM_CONTACT_REQUIRED | Faltou o telefone ou o e-mail que o formulário usa para achar o contato. |
402 ERR_FEATURE_NOT_IN_PLAN | O plano da conta não tem Formulários. |
413 ERR_FORM_TOO_LARGE | Respostas acima de 32 KB. |
ERR_FORM_ID_OR_SLUG_REQUIRED e ERR_FORM_NOT_FOUND. O envio completo depende de um formulário criado na sua conta: faça o primeiro teste com o seu próprio telefone.Logs de chamadas recebidas/realizadas.
Rotas
| Método | Rota | Descrição |
|---|---|---|
GET | callLog/list?page=1&limit=20 | Lista chamadas. Ordena com orderBy e orderDirection; não filtra por período. |
GET | callLog/show/{id} | Detalhe da chamada. |
GET | wavoip/calls?page=1&limit=20 | Lista chamadas de voz IP. Filtros: startDate, endDate, direction, callStatus, phone, contactId, ticketId, userId e queueId. Use esta rota para recortar por data. |
GET | wavoip/calls/{id} | Detalhe da chamada de voz IP. |
Listagens auxiliares para montar integrações.
Rotas
| Método | Rota | Descrição |
|---|---|---|
GET | listChatFlows | Fluxos de chatbot do tenant. |
GET | listAutoReplies | Respostas automáticas. |
GET | listFastReplies | Respostas rápidas. |
🪝 Webhooks
Webhooks são notificações que o NimoChat Pro+ envia automaticamente para uma URL do seu sistema sempre que algo acontece na plataforma — uma nova mensagem chega, um ticket é criado, um atendimento é finalizado.
Em vez de seu sistema ficar perguntando à API "tem mensagem nova?" a cada minuto (polling), o NimoChat avisa em tempo real quando algo acontece. Isso é mais eficiente, mais rápido e consome menos recursos.
Configurando o Webhook
A configuração é feita no painel administrativo do NimoChat Pro+ em poucos cliques:
- Faça login como Administrador.
- Acesse Integrações > Webhook no menu.
- Ative a opção "Ativar webhook".
- Informe a URL do seu sistema que vai receber as notificações (precisa ser HTTPS pública).
- Opcionalmente, ative "Receber eventos de mensagem" para receber notificações também das mensagens individuais (não apenas dos tickets).
- Salve as alterações.
localhost, 192.168.x.x) não funcionam. Use um servidor público, ngrok para testes ou um serviço como n8n/Make/Pipedream.
Estrutura do payload
Toda notificação é enviada como POST para sua URL com Content-Type: application/json. O corpo da requisição segue esta estrutura:
{
"method": "...", // tipo do evento (opcional)
"tenantId": 123, // ID da sua conta
"ticketId": 98765, // ID do ticket relacionado
"msg": { // dados da mensagem
"body": "texto da mensagem",
"fromMe": false, // true = atendente enviou, false = contato enviou
"from": "5511999999999@s.whatsapp.net"
},
"ticket": { // dados do ticket
"id": 98765,
"tenantId": 123,
"userId": null, // null = não atribuído
"queueId": 5, // ID da fila
"createdAt": "2026-04-06T13:00:00.000Z",
"contact": {
"id": 456,
"name": "João Silva",
"number": "5511999999999",
"wallets": [{ "id": 7 }]
}
}
}
Campos principais
| Campo | Tipo | Descrição |
|---|---|---|
method | string | Tipo do evento. Quando ausente ou vazio, indica evento de entrada (mensagem recebida ou ticket criado). |
tenantId | int | ID da sua conta. Sempre valide para garantir que o webhook é da sua conta. |
ticketId | int | ID do ticket relacionado ao evento. |
msg.body | string | Texto da mensagem (em mensagens de texto). |
msg.fromMe | boolean | true se a mensagem foi enviada pelo atendente, false se foi recebida do contato. |
ticket.userId | int|null | null indica ticket não atribuído (oportunidade de distribuição automática). |
ticket.contact.number | string | Telefone do contato (sem prefixos do WhatsApp). |
Tipos de eventos
O campo method identifica o tipo do evento. Os principais valores são:
| Evento | Quando dispara |
|---|---|
| (vazio) — Mensagem recebida | O contato enviou uma mensagem. msg.fromMe = false e method ausente. Frequentemente acompanhado de criação de ticket novo. |
| (vazio) — Novo ticket | Um novo ticket foi criado a partir de uma conversa de entrada. ticket.userId = null. |
message_send | O atendente enviou uma mensagem pelo painel. msg.fromMe = true. |
message_send_uazapi | Mensagem enviada por uma sessão WhatsApp via QR Code (não-oficial). |
message_send_waba / message_sent_waba | Mensagem enviada pela API oficial do WhatsApp Business (Cloud API). |
ack | Confirmação de leitura/entrega do WhatsApp (entregue, lido, ouvido). |
presence | Atualização de presença do contato (online, offline, digitando). |
method e com fromMe = false) e ignora os eventos ack, presence e os de envio. Isso evita ruído e processa só o que é acionável.
Exemplos de payloads reais
Mensagem de texto recebida
{
"msg": {
"fromMe": false,
"body": "Olá, gostaria de saber sobre o produto X",
"from": "5511999999999@s.whatsapp.net"
},
"ticket": {
"id": 12345,
"tenantId": 2,
"userId": null,
"queueId": 3,
"createdAt": "2026-04-06T13:00:00.000Z",
"contact": {
"id": 456,
"name": "João Silva",
"number": "5511999999999",
"wallets": []
}
}
}
Mídia recebida (áudio, imagem, documento)
{
"msg": {
"fromMe": false,
"content": [
{ "type": "audio", "url": "https://media.../audio.ogg" }
]
},
"ticket": {
"id": 12346,
"tenantId": 2,
"contact": { "id": 456, "number": "5511999999999" }
}
}
msg.body pode estar vazio e o conteúdo vir em msg.content como array. Sempre faça type checking no seu código antes de processar.
Mensagem enviada pelo atendente (filtrar)
{
"method": "message_send_uazapi",
"msg": { "fromMe": true, "body": "Olá! Em que posso ajudar?" },
"ticket": { "id": 12345, "tenantId": 2 }
}
Confirmação de leitura (filtrar)
{
"method": "ack",
"ticketId": 12345
}
Exemplo de receiver (Node.js)
Receiver simples em Node.js + Express que processa apenas mensagens recebidas:
const express = require('express'); const app = express(); app.use(express.json()); // Métodos a ignorar (saída + ruído) const IGNORE = ['message_send', 'message_send_uazapi', 'message_send_waba', 'message_sent_waba', 'ack', 'presence']; app.post('/webhook/nimochat', (req, res) => { const payload = req.body; // 1. Filtrar eventos que não interessam if (IGNORE.includes(payload.method)) return res.sendStatus(200); // 2. Validar tenant (segurança) if (payload.ticket?.tenantId !== SEU_TENANT_ID) return res.sendStatus(403); // 3. Processar apenas mensagens recebidas if (payload.msg?.fromMe === false) { const contact = payload.ticket?.contact; const body = typeof payload.msg.body === 'string' ? payload.msg.body : ''; console.log(`Nova mensagem de ${contact?.name}: ${body}`); // Aqui você integra com seu CRM, dispara alerta, etc. } res.sendStatus(200); }); app.listen(3000);
Segurança e boas práticas
- HTTPS obrigatório — sempre use URLs com SSL válido. Webhooks com HTTP simples podem não funcionar.
- Valide o
tenantId— confira se o ID da conta no payload bate com o seu. Se não bater, rejeite com HTTP 403. - Responda rápido (HTTP 200) — o webhook tem timeout. Se sua lógica é demorada, responda 200 imediatamente e processe em background (fila).
- Idempotência — use
ticket.id+msg.from+ timestamp para evitar processar a mesma mensagem 2x se houver retentativa. - Type checking — sempre verifique o tipo dos campos antes de usar (especialmente
msg.bodyque pode ser string ou ausente). - Logue tudo no início — durante a integração, logue payloads completos. Eles são sua única fonte de verdade sobre o que chega.
- IP whitelist (opcional) — se possível, restrinja o endpoint apenas a IPs conhecidos do servidor NimoChat.
💡 Casos de uso reais
1. Disparo em massa segmentado por tag
Você quer enviar uma promoção para todos os contatos com a tag "Lead Quente". Em vez de exportar a lista manualmente, busque os contatos via API e dispare via n8n / Make.
Passo 1 — Buscar contatos com a tag
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/contacts/search' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "tagId": 42, "limit": 500 }'
Passo 2 — Para cada contato, enviar a mensagem
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "number": "5511999999999", "body": "Oferta especial só para você! 30% OFF até hoje." }'
2. Distribuição automática de leads para vendedores
Quando um novo lead chega, atribua automaticamente para um vendedor disponível usando a função de carteirização (wallet).
Atribuir contato à carteira do vendedor
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/updateContactWallet' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "contactId": 4567, "walletId": 12 }'
Combine com o webhook de novo ticket: quando o NimoChat avisar que um novo ticket foi criado, sua aplicação consulta qual vendedor está disponível (lógica round-robin, menor carga, especialidade) e atribui via API.
3. Sincronizar contatos do CRM com o NimoChat
Toda vez que um novo contato é cadastrado no seu CRM, replique-o automaticamente para o NimoChat:
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/createContact' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "name": "Maria Oliveira", "number": "5511988887777", "email": "maria@empresa.com", "extraInfo": [ { "name": "empresa", "value": "ACME Ltda" }, { "name": "cargo", "value": "Diretora Comercial" } ] }'
4. Cadastrar atendentes via integração com RH
Quando um novo colaborador é admitido no seu sistema de RH, crie automaticamente o usuário (atendente) no NimoChat:
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/createUser' \ --header 'Authorization: Bearer SEU_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "name": "Carlos Santos", "email": "carlos.santos@empresa.com", "password": "SenhaTemp123!", "profile": "user" }'
5. Humanizar bots — mostrar "digitando..." antes da resposta
Antes do seu bot enviar uma resposta automática, envie um sinal de presence "typing" para humanizar a interação:
# 1. Envia "digitando..." (typing) curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/sendPresence' \ --header 'Authorization: Bearer SEU_TOKEN' \ --data '{ "ticketId": 12345, "state": "typing" }' # 2. Aguarda 2-4 segundos sleep 3 # 3. Envia a mensagem real curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID' \ --header 'Authorization: Bearer SEU_TOKEN' \ --data '{ "number": "5511999999999", "body": "Resposta do bot" }'
6. Classificar tickets durante o atendimento
Use addTag para classificar o ticket sem perder as tags anteriores. Por exemplo, ao detectar uma palavra-chave no texto da mensagem:
curl --request POST \ --url 'https://SUA_URL_BASE/v2/api/external/SEU_API_ID/addTag' \ --header 'Authorization: Bearer SEU_TOKEN' \ --data '{ "ticketId": 12345, "tagId": [42, 87] }'
📚 Referência completa de endpoints
A coleção do Postman é gerada a partir desta página: tem todas as rotas daqui, cada uma com corpo de exemplo, os campos, os avisos e o link para o cartão correspondente. O Postman monta o código em várias linguagens (cURL, Node.js, Python, PHP, Go, Java).
Abra a coleção, clique em qualquer endpoint, e copie o snippet na linguagem desejada usando o painel "Code" (lateral direita).
Endpoints por categoria
Resumo de tudo que está disponível na coleção:
📅 Agendamentos e Lembretes
Crie e gerencie agendamentos e lembretes automáticos.
📣 Campanhas
Crie, gerencie e dispare campanhas de marketing em massa.
🔌 Canais e Sessões
Gerencie conexões WhatsApp, escaneie QR Codes, inicie e finalize sessões.
👤 Contatos (avançado)
🏗️ CRM - Pipeline
Gerencie pipelines (funis) e estágios do CRM.
📊 Dashboard
Métricas e gráficos para BI / dashboards externos.
📤 Envio em Lote (Bulk)
Disparos em massa de mensagens com controle de progresso.
📂 Galeria de mídias
👥 Grupos WhatsApp
Crie e gerencie grupos do WhatsApp.
🏷️ Kanban / Tags / Motivos / Filas
CRUD completo de objetos auxiliares.
🔍 Listagens utilitárias
📞 Logs de Chamadas
📨 Mensagens (extras)
👥 Mensagens em Grupo
💼 Oportunidades (CRM)
📋 Templates WABA (API Oficial)
🎫 Tickets (extras)
✅ To-Do List
❓ FAQ — Perguntas frequentes
Posso testar sem código?
Sim. Acesse a coleção do Postman, clique em qualquer endpoint, preencha as variáveis (token, URL base, API ID) e clique em "Send". É a forma mais rápida de testar.
Como gerar exemplos de código em outras linguagens?
No Postman, abra o endpoint, clique no ícone { } (Code Snippets) na lateral direita e escolha a linguagem: cURL, Node.js, Python, PHP, Java, Go, C#, Ruby, etc.
Existe limite de requisições (rate limit)?
Sim. Use a API com bom senso — picos muito altos podem ser bloqueados. Para disparos em massa, use os endpoints específicos de Bulk com delay entre mensagens (recomendado: 5-10 segundos).
Como funciona a autenticação Bearer?
Você gera um token no painel admin (menu API) e envia ele em todas as requisições no header Authorization: Bearer SEU_TOKEN. O token é específico da sua conta e isola seus dados.
O que é o apiId no URL?
É o identificador único da sua chave de API. É gerado junto com o token quando você cria uma nova API no painel. Cada chave pode estar associada a uma conexão WhatsApp específica.
Por que minhas mensagens não chegam ao destino?
Possíveis causas: (1) número formatado errado — sempre use DDI+DDD+número (ex: 5511999999999), (2) conexão WhatsApp desconectada — verifique no painel, (3) número do destinatário não tem WhatsApp, (4) o WhatsApp pode ter bloqueado por excesso de mensagens.
O webhook não está chegando, o que fazer?
Confira: (1) URL configurada está correta e é HTTPS pública, (2) seu servidor responde com HTTP 200 em até 15 segundos, (3) a opção "Receber eventos de mensagem" está ativada se você quer receber mensagens individuais, (4) seu firewall não está bloqueando os IPs do NimoChat.
Onde reportar bugs ou sugerir novos endpoints?
Entre em contato pelo nosso canal de suporte — vamos avaliar e priorizar. Atualizações da API são notificadas via release notes no Postman.