Skip to content

API interna do painel ​

INFO

Estas são as rotas que as telas do painel usam, com o login de uma pessoa. Para integrar outro sistema, prefira a API v1 com chave.

Todas as rotas abaixo ficam em /api/ e pedem Authorization: Bearer <token> (veja Como usar a API). Onde aparece (admin), só admin e dono podem chamar.

Eu e a equipe ​

MétodoRotaCorpo / QueryResposta
GETat/equipe/eu{ id, nome, email, papel, presenca, presenca_motivo, max_simultaneas, setores:[ids], supervisiona:[ids], empresa:{id,nome,marca} }
POSTat/equipe/presenca{ presenca:'online'|'pausa'|'offline', motivo? }{ ok, presenca }
GETat/equipe[{ id, nome, email, papel, presenca, presenca_motivo, max_simultaneas, visto_em, setores:[{id,nome,cor,supervisor}], ativas }]
POSTat/equipe (admin){ nome, email, senha(≥10), papel:'admin'|'supervisor'|'atendente', max_simultaneas?, setores?:[ids] }pessoa
PATCHat/equipe/:id (admin){ nome?, papel?, max_simultaneas?, setores? }
DELETEat/equipe/:id (admin){ ok } (as conversas da pessoa voltam para a fila)

Conversas ​

Objeto conversa (lista e detalhe):

GrupoCampos
Identificaçãoid, protocolo, status: bot | fila | aberta | pendente | adiada | avaliacao | encerrada
Classificaçãoprioridade: baixa | normal | alta | urgente; sentimento; etiquetas[]
Préviaultima_mensagem, ultima_mensagem_em, nao_lidas
Temposentrou_fila_em, atribuida_em, primeira_resposta_em, encerrada_em, sla_avisado (0 ok, 1 ≥ 50%, 2 ≥ 80%, 3 estourado), sla_primeira_resp_s
Contatocontato_id, contato_nome, contato_telefone, contato_email
Setor e atendentesetor_id, setor_nome, setor_cor (1–8), atendente_id, atendente_nome
Canalcanal_id, canal_tipo: webchat | evolution | cloud; canal_nome
IAresumo_ia
MétodoRotaCorpo / QueryResposta
GETat/conversasaba: minhas|fila|bot|encerradas|todas, setor_id, busca, limite, antes (ISO, paginação por ultima_mensagem_em)[conversa]
GETat/conversas/contagens{ minhas, fila, bot, todas }
GETat/conversas/:idconversa + contato{...}, qualidade (auditoria IA ou null), csat ({nota} ou null), historico (conversas anteriores)
GETat/conversas/:id/mensagensantes (id)[mensagem] em ordem crescente (100 por página); zera nao_lidas
GETat/conversas/:id/eventos[{ tipo, usuario_nome, dados, criado_em }] (criada, fila, atribuida, transferida, primeira_resposta, csat, encerrada, alerta, triagem_ia, ia_fontes…)
POSTat/conversas/:id/mensagens{ texto, privada?, resposta_a?, midia?:{ base64, mime, nome?, tipo:'imagem'|'audio'|'documento' } }mensagem. Responder conversa da fila assume ela. privada:true = nota interna (@Nome avisa a pessoa)
POSTat/conversas/:id/mensagens/:mid/reenviarsó para status falhou
POSTat/conversas/:id/lidazera não lidas
POSTat/conversas/:id/assumirconversa
POSTat/conversas/:id/transferir{ setor_id? | usuario_id?, nota? }conversa
PATCHat/conversas/:id{ prioridade?, etiquetas?, status?:'aberta'|'pendente', adiada_ate?: ISO }conversa
POSTat/conversas/:id/encerrar{ motivo, mensagem_final?, csat?:bool }conversa (avaliacao se enviou a pesquisa)
POSTat/conversas/:id/reabrirconversa
POSTat/conversas{ canal_id, contato_id, texto }inicia conversa (WhatsApp)
POSTat/conversas/:id/ia/sugerir{ sugestoes:[3 textos], fontes:[títulos] }
POSTat/conversas/:id/ia/resumo{ resumo }
POSTat/conversas/:id/ia/auditarauditoria de qualidade
POSTat/conversas/ia/reescrever{ texto, tom:'cordial'|'formal'|'curto'|'corrigir'|'empatico' }{ texto }

Objeto mensagem:

CampoValores
direcaoentrada | saida | sistema
autor_tipocontato | usuario | bot | ia | sistema
autor_nometexto
tipotexto | menu | audio | imagem | documento | video | localizacao
conteudotexto
midia{ url, mime, nome, opcoes?[{id,titulo}] }
privadaboolean (nota interna)
statuspendente | enviada | entregue | lida | falhou | nota
erro, transcricaotexto do áudio
criado_emdata

As URLs de mídia são relativas (/api/at/midias/...), assinadas e com validade. Elas funcionam direto em <img> e <audio>.

Setores, horários, respostas, etiquetas ​

  • GET/POST at/setores, PATCH/DELETE at/setores/:id, PUT at/setores/:id/membros { membros:[{usuario_id, supervisor}] }.
  • Campos do setor:
    • nome, cor(1–8), distribuicao: menor_carga | rodizio | carteira | manual;
    • horario_id, sla_primeira_resp_s, sla_resolucao_s, escalar_apos_s, transbordo_setor_id;
    • msg_fila, msg_fora_horario, msg_encerramento, enviar_csat, ativo;
    • na lista também vem membros[{id,nome,supervisor,presenca,max_simultaneas,papel}].
  • GET/POST at/horarios, PATCH at/horarios/:id. Campos:
    • nome;
    • grade: { "0".."6": [["09:00","12:00"],["13:00","18:00"]] } (0 = domingo);
    • feriados: ["2026-12-24"];
    • feriados_nacionais: bool.
  • GET/POST at/respostas, PATCH/DELETE at/respostas/:id. Campos: atalho (minúsculas, sem espaço), texto (aceita ), setor_id?.
  • GET/POST at/etiquetas, DELETE at/etiquetas/:id. Campos: nome, cor.

Canais ​

  • GET/POST at/canais, PATCH/DELETE at/canais/:id (admin).
  • Criar:
    • { tipo:'webchat'|'evolution'|'cloud', nome, config, segredos, fluxo_id?, setor_padrao_id? }.
  • Config por tipo:
    • webchat: { titulo, subtitulo, saudacao, cor:'#rrggbb', posicao:'direita'|'esquerda', dominios:['meusite.com'], pedir_telefone, pedir_email, texto_privacidade, link_privacidade, whatsapp };
    • evolution: { url, instancia } com segredos { apikey };
    • cloud: { phone_number_id, versao } com segredos { token, app_secret }.
  • Resposta: segredos mostra só quais estão preenchidos ({apikey:true}), mais webhook_url, snippet (widget), capacidades e status_conexao.
  • Segredos: mandar null apaga; omitir mantém.

Fluxos ​

MétodoRotaCorpoResposta
GETat/fluxos/tipos[{ tipo, grupo, titulo, espera, final }]
GETat/fluxos[{ id, nome, descricao, versao_publicada, tem_rascunho, canais }]
GETat/fluxos/:id{ ..., rascunho:{nodes,edges,viewport}, versoes:[{numero,publicado_em,publicado_por}], validacao:{erros,avisos} }
POSTat/fluxos{ nome, descricao?, modelo?:'vazio'|'boas_vindas', definicao? }fluxo
PUTat/fluxos/:id{ nome?, descricao?, rascunho? }fluxo + validacao
POSTat/fluxos/:id/publicar{ numero, avisos } (400 com os erros)
POSTat/fluxos/:id/restaurar/:numerovolta o rascunho para a versão
POSTat/fluxos/validardefinição{ erros, avisos }
POSTat/fluxos/simular{ definicao, respostas:[textos] }{ mensagens:[{de:'bot'|'cliente'|'sistema', texto, no, opcoes?}], variaveis }
POSTat/fluxos/gerar{ pedido }{ nome, definicao, validacao } (IA)

Definição: é o formato do Vue Flow.

  • Nó: { id, type, position:{x,y}, data }.
  • Aresta: { id, source, target, sourceHandle }.
  • sourceHandle é o nome da saída.

Tipos de nó, data e saídas:

TipodataSaídas
inicio—saida
mensagem{ texto }saida
menu{ texto, opcoes:[{id,titulo}], espera_min, tentativas, variavel?, msg_invalido? }o id de cada opção, invalido, timeout
pergunta{ texto, variavel, validacao: texto|numero|email|cpf|cnpj|cpf_cnpj|telefone|data|regex, regex?, salvar_no_contato?: nome|email|<campo>, espera_min, tentativas, msg_invalido? }resposta, invalido, timeout
condicao{ regras:[{campo, op: igual|diferente|contem|vazio|nao_vazio|maior|menor, valor}], modo:'e'|'ou' }sim, nao
horario{ setor_id? }dentro, fora
esperar{ minutos }saida
ir_para{ no_id }—
definir_variavel{ variavel, valor }saida
atualizar_contato{ nome?, email?, etiqueta?, campo?, valor?, opt_out? }saida
http{ metodo, url (https), headers?, corpo?, salvar_em? }ok, erro
ia_agente{ agente_id? | instrucoes, usar_conhecimento, max_turnos, espera_min }concluiu, humano, erro
ia_classificar{ categorias:[{id,titulo,descricao}], variavel? }o id de cada categoria, incerto
ia_extrair{ campos:[{nome,descricao}] }saida
transferir{ setor_id | usuario_id, prioridade?, mensagem?, resumo_ia?, avisar_fila? }fim
notificar{ setor_id? | usuario_id?, texto }saida
encerrar{ mensagem?, motivo?, csat? }fim

Todos os nós aceitam data.titulo, um nome opcional exibido no canvas. Nos textos, , e são substituídos.

IA: agentes e base de conhecimento ​

  • GET/POST at/agentes, PATCH/DELETE at/agentes/:id. Campos: nome, instrucoes, usar_conhecimento, modelo?, ativo.

  • GET at/conhecimento → [{ id, titulo, fonte, tamanho, trechos, criado_em }].

  • GET at/conhecimento/:id.

  • GET at/conhecimento/buscar?q= → [{ titulo, texto, rank }] (para testar).

  • POST at/conhecimento aceita três formatos:

    • {tipo:'texto', titulo, texto};
    • {tipo:'url', url};
    • {tipo:'pdf', nome, base64}.

    Todos aceitam setor_id?.

  • DELETE at/conhecimento/:id.

Contatos (LGPD) ​

  • GET at/contatos?busca=&pagina=.
  • PATCH at/contatos/:id { nome?, email?, etiquetas?, campos?, carteira_usuario_id?, opt_out? }.
  • GET at/contatos/:id/exportar (admin) devolve tudo o que há sobre o titular.
  • DELETE at/contatos/:id (admin) apaga o contato, as conversas e as mídias.

Métricas ​

  • GET at/metricas/ao-vivo:
    • filas: [{ id, nome, cor, aguardando, em_atendimento, no_bot, maior_espera_s, online, membros }];
    • hoje: { novas_hoje, na_fila, em_atendimento, no_bot, tme_s };
    • csat: { media, respostas, satisfeitos_pct };
    • sla: { pct, em_risco };
    • equipe: [{ id, nome, presenca, presenca_motivo, ativas, max_simultaneas, tma_s, setores }];
    • risco: [conversas].
  • GET at/metricas/periodo?inicio=&fim= (ISO; padrão 7 dias):
    • resumo: { conversas, encerradas, tme_mediana_s, tme_media_s, tme_p90_s, frt_mediana_s, tma_media_s, resolucao_media_s, resolvidas_bot, abandonadas, entraram_fila };
    • csat, qualidade;
    • porDia, porHora, porSetor, porAtendente, motivos, iaUso.
  • GET at/metricas/qualidade:
    • piores: [{ conversa_id, nota, resumo, problemas, criterios, atendente, contato, protocolo }];
    • criterios: { cordialidade, agilidade, resolucao, precisao, vendas, processo }.

Notificações ​

  • GET at/notificacoes → [{ id, tipo, titulo, texto, conversa_id, lida_em, criado_em }].
  • POST at/notificacoes/lidas { ids? }.

Tempo real (Socket.IO) ​

Equipe:

  • Conexão: io(location.origin, { path: '/api/socket', auth: { token: <JWT> } }).
  • Para receber "digitando" de uma conversa: emit('conversa:abrir', id).
  • emit('digitando', { conversaId, ativo }) repassa para o visitante do chat do site.
EventoDados
conversa:atualizadaconversa
mensagem:nova{ conversaId, mensagem }
mensagem:status{ conversaId, id, status, erro? }
mensagem:transcricao{ conversaId, id, transcricao }
digitando{ conversaId } (visitante do site digitando)
notificacaonotificação
presenca{ usuarioId, presenca, motivo }
alerta:som{ conversaId }

Visitante do widget:

  • Conexão: namespace /webchat, auth: { token: <token do visitante> }.
  • Recebe mensagem (pública), digitando { ativo } e encerrada.
  • Envia digitando.

Configurações, perfil, fotos e integrações ​

Empresa (admin) ​

  • GET at/empresa → { id, nome, marca:{ cor, logo_url }, config:{ inatividade } }
  • PATCH at/empresa → { nome?, marca?:{ cor? }, config?:{ inatividade? } }
    • inatividade: { ativo, aplicar_em:['aberta','pendente','bot'], lembretes:[{ minutos, texto }], encerrar_minutos, mensagem_encerramento }
    • Regra: depois da nossa última mensagem sem resposta do cliente, cada lembrete é enviado minutos após a mensagem anterior. Depois do último, passados encerrar_minutos, a conversa é encerrada com mensagem_encerramento, motivo inatividade e sem avaliação. Os textos aceitam .
  • POST at/empresa/logo { base64, mime } → { logo_url } · DELETE at/empresa/logo

Meu perfil (qualquer pessoa logada) ​

  • GET at/equipe/eu passa a trazer foto_url, assinatura e preferencias:{ som, notificacoes_navegador, assinar_mensagens }.
  • PATCH at/equipe/eu { nome?, assinatura?, preferencias? }
    • Com assinar_mensagens, o WhatsApp recebe *Assinatura* na 1ª linha das mensagens da pessoa. O padrão da assinatura é o primeiro nome.
  • POST at/equipe/eu/foto { base64, mime } → { foto_url } · DELETE at/equipe/eu/foto
  • A senha continua em POST auth/senha { senha_atual, senha_nova } (rota já existente).
  • Fotos em listas e conversas:
    • foto_url em at/equipe, atendente_foto_url e contato_foto_url na conversa, autor_foto_url na mensagem e foto_url no contato.
    • São URLs relativas, abertas direto em <img>. A foto do contato do WhatsApp é buscada sozinha na Evolution.

Detalhe da conversa ​

  • GET at/conversas/:id traz também sdr (ficha do agente de IA de prospecção do n8n, quando o telefone bate): { etapa, status, negocio, necessidade, orcamento, oferta, objecoes, resumo, reuniao_em, ultima_nota, numero, link }, ou null.
  • GET at/conversas/:id/integracoes → [{ integracao_id, nome, tipo:'whmcs', encontrado, erro?, cliente?, servicos[], faturas[], dominios[], tickets[], resumo?:{ faturas_abertas, valor_em_aberto } }], com:
    • cliente: { id, nome, empresa, email, telefone, status, criado_em, link }
    • servicos: [{ id, produto, dominio, status, valor, ciclo, vencimento, link }]
    • faturas: [{ id, numero, status, total, vencimento, link }]
    • dominios: [{ dominio, status, vencimento }]
    • tickets: [{ id, assunto, status, departamento, atualizado_em, link }]

Integrações (admin) ​

  • GET/POST at/integracoes, PATCH/DELETE at/integracoes/:id, POST at/integracoes/:id/testar → { ok, mensagem }.
  • Criar: { tipo:'whmcs', nome, config:{ url }, segredos:{ identifier, secret, accesskey? } }
    • url é o endereço do WHMCS, por exemplo https://www.inneed.com.br/clientes.
    • Os segredos voltam só como true/false.
    • O WHMCS precisa liberar o IP do servidor do painel (177.11.55.67) em Setup → General → Security → API IP Access Restriction, ou usar accesskey.
  • Agentes de IA ganham usar_integracoes: o resumo do cliente no WHMCS (serviços, faturas em aberto) entra no contexto do agente.

Chat do site (canal webchat): configuração ​

Em config do canal (todos opcionais):

CampoValor
titulo_boas_vindasex.: "Olá! Seja bem-vindo ao atendimento da In Need Cloud."
subtitulofrase abaixo do título
tempo_respostaminutos | hora | dia
titulo_lancadortexto ao lado do botão, ex.: "Fale conosco no chat"; vazio = só o ícone
mensagem_formulariotexto acima dos campos
campos[{ chave, tipo:'text'|'email'|'tel'|'textarea'|'select', rotulo, placeholder, obrigatorio, ativo, opcoes?:[texto] }]. Chaves padrão: nome, email, telefone; outras chaves (slug) vão para contato.campos e para conversa.formulario. Padrão: nome, email e telefone, todos obrigatórios
mostrar_equipefotos da equipe online na tela inicial
permitir_anexos
permitir_encerrar
cor, posicao, dominios, texto_privacidade, link_privacidade, whatsappjá existentes
  • GET at/webchat/:chave/config passa a devolver esses campos e mais equipe:[{ nome, foto_url }] (até 3 online) e logo.
  • POST at/webchat/:chave/sessao { campos:{ chave: valor }, consentimento:true, pagina? }. Continua aceitando nome, telefone e email soltos.
  • POST at/webchat/encerrar (Bearer do visitante): o visitante encerra a conversa.

Nós de fluxo: lembrete antes do tempo esgotar ​

menu, pergunta e ia_agente aceitam lembrete_min e lembrete_texto. Se o cliente não responder em lembrete_min, o texto é enviado uma vez; em espera_min sai pela saída timeout (no agente, concluiu). Também aceitam msg_timeout, a mensagem de encerramento quando não há ligação na saída de tempo esgotado.

Canal Evolution: conexão automática ​

  • POST at/canais/:id/conectar (admin): aponta o webhook da instância (/webhook/set) para o painel, com os eventos MESSAGES_UPSERT, MESSAGES_UPDATE e CONNECTION_UPDATE e mídia em base64. Devolve o status.
  • GET at/canais/:id/status → { conectado, estado, webhook_ok, webhook_atual, qr (base64 PNG quando desconectado), mensagem }.