Catálogos

As rotas de catálogo devolvem os identificadores que o resto da API pede: conexões (números de WhatsApp), departamentos, atendentes, modelos de mensagem da API oficial, etiquetas e motivos de encerramento, além das informações da própria chave. Todas são de leitura e ficam liberadas para qualquer chave ativa.

Visão geral

Antes de enviar uma mensagem por um número específico, transferir para um departamento, atribuir um atendente ou encerrar com um motivo, a integração precisa dos ids desses cadastros. As sete rotas desta página existem para isso:

RotaDevolveUsado em
chave/infoA própria chave e o servidorTeste de conexão, conferência de escopos e fuso horário
conexoes/listarNúmeros de WhatsAppconexao_id em envios, abertura de atendimento, filtros e modelos
departamentos/listarDepartamentosdepartamento_id em transferência, abertura de atendimento, ordens de serviço, agenda, filtros e indicadores
atendentes/listarAtendentesatendente_id em transferência e abertura; responsavel_id em ordens de serviço e agenda
modelos/listarModelos da API oficialmodelo_id em mensagens/enviar_modelo
etiquetas/listarEtiquetas de conversaconversas/etiquetas e o filtro etiqueta_id
motivos/listarMotivos de encerramentomotivo_id em conversas/encerrar
  • Escopo: nenhum. Qualquer chave ativa pode chamar, mesmo com todas as permissões desligadas.
  • Método: GET (POST também é aceito).
  • Paginação: não há. Cada rota devolve a lista inteira, que em um provedor costuma ter de alguns a algumas dezenas de itens.
  • Contagem: as chamadas de catálogo contam no uso e no limite por minuto da chave, como qualquer outra.

Os exemplos em PHP e Python desta página usam a função chatisp() apresentada em Endereço e autenticação: ela monta a URL, envia a chave no cabeçalho e devolve a resposta decodificada.


Informações da chave

GET /api_publica.php?r=chave/info

Mostra a chave que fez a chamada (nome, escopos e limite por minuto) e dados do servidor (versão da API, fuso horário, relógio e plano). É a melhor rota para testar endereço e chave, e para a integração conferir na inicialização se tem os escopos de que precisa.

Parâmetros: nenhum.

terminal
curl -s "https://atendimento.seuprovedor.com.br/api_publica.php?r=chave/info" \
  -H "Authorization: Bearer $CHATISP_CHAVE"
PHP
$info = chatisp('chave/info');
$faltando = array_diff(['mensagens_enviar', 'tickets_gerir'], $info['chave']['escopos']);
if ($faltando) {
    die('Ligue na chave: ' . implode(', ', $faltando) . PHP_EOL);
}
Python
info = chatisp("chave/info")
faltando = {"mensagens_enviar", "tickets_gerir"} - set(info["chave"]["escopos"])
if faltando:
    raise SystemExit(f"Ligue na chave: {', '.join(faltando)}")
resposta (HTTP 200)
{
  "ok": true,
  "chave": {
    "id": 3,
    "nome": "ERP financeiro",
    "prefixo": "cisp_7f3a9…",
    "escopos": ["mensagens_enviar", "conversas_ler", "atendimentos_abrir"],
    "cota_minuto": 60
  },
  "servidor": {
    "api_versao": "1",
    "fuso_horario": "America/Sao_Paulo",
    "agora": "2026-10-01T09:30:12-03:00",
    "plano": "PREMIUM"
  }
}
CampoTipoDescrição
chave.idinteiroIdentificador da chave no painel.
chave.nomestringO Nome dado à chave. É o nome que aparece no histórico das ações feitas por ela.
chave.prefixostringO começo da chave, igual ao mostrado na lista do painel. A chave completa nunca é devolvida pela API.
chave.escoposlistaEscopos ligados, na ordem da tela. Veja a tabela em Permissões da chave.
chave.cota_minutointeiroLimite por minuto. 0 = sem limite.
servidor.api_versaostringVersão da API, a mesma do cabeçalho X-ChatISP-Api-Versao.
servidor.fuso_horariostringFuso horário do servidor (nome IANA). Datas sem fuso enviadas à API são lidas nele.
servidor.agorastringRelógio do servidor em ISO 8601. Útil para medir a diferença para o relógio do seu sistema.
servidor.planostringNome do plano em vigor (PREMIUM, GOLD, ENTERPRISE, CUSTOM ou TRIAL durante o teste).

Erros: só os de acesso, comuns a todas as rotas (autenticacao, chave_invalida, plano, cota_excedida).


Conexões (números de WhatsApp)

GET /api_publica.php?r=conexoes/listar

Lista todas as conexões cadastradas, conectadas ou não, em ordem de nome. Cada conexão é um número de WhatsApp ligado ao ChatISP por QR Code ou pela API oficial da Meta (veja Conexões de WhatsApp).

Parâmetros: nenhum.

terminal
curl -s "https://atendimento.seuprovedor.com.br/api_publica.php?r=conexoes/listar" \
  -H "Authorization: Bearer $CHATISP_CHAVE"
PHP
// Um número = uma linha: descarta a perna não principal dos gêmeos
$numeros = array_filter(chatisp('conexoes/listar')['conexoes'], fn($c) => $c['principal']);
foreach ($numeros as $c) {
    echo "{$c['id']}  {$c['nome']}  {$c['telefone']}  {$c['estado']}\n";
}
Python
# Um número = uma linha: descarta a perna não principal dos gêmeos
for c in chatisp("conexoes/listar")["conexoes"]:
    if c["principal"]:
        print(c["id"], c["nome"], c["telefone"], c["estado"])
resposta (HTTP 200)
{
  "ok": true,
  "conexoes": [
    {
      "id": 1,
      "nome": "Atendimento",
      "tipo": "qr",
      "estado": "conectada",
      "telefone": "5544999990000",
      "nome_conta": "Fibra Exemplo",
      "gemea_id": 2,
      "principal": true
    },
    {
      "id": 2,
      "nome": "Atendimento (API oficial)",
      "tipo": "api_oficial",
      "estado": "conectada",
      "telefone": "5544999990000",
      "nome_conta": "Fibra Exemplo",
      "gemea_id": 1,
      "principal": false
    },
    {
      "id": 4,
      "nome": "Comercial",
      "tipo": "qr",
      "estado": "desconectada",
      "telefone": "5544999991111",
      "nome_conta": "Fibra Exemplo Vendas",
      "gemea_id": null,
      "principal": true
    }
  ]
}
CampoTipoDescrição
idinteiroO conexao_id usado nas outras rotas.
nomestringNome dado à conexão no painel.
tipostringqr (conectada pelo QR Code do aplicativo) ou api_oficial (API oficial da Meta).
estadostringconectada, conectando, desconectada ou erro. Só conexões conectada enviam mensagens.
telefonestringO número do WhatsApp, só dígitos. Pode vir vazio numa conexão que ainda não foi pareada.
nome_contastringNome do perfil do WhatsApp (o que o cliente vê).
gemea_idinteiro ou nullNa conexão gêmea, o id da outra perna do mesmo número. null nas conexões simples.
principalbooleanoSe é a perna onde nascem as conversas novas do número. Sempre true nas conexões simples.

Erros: só os de acesso.

Número gêmeo: QR e API oficial no mesmo número

Um mesmo número de WhatsApp pode estar ligado ao ChatISP pelos dois caminhos ao mesmo tempo: pelo QR Code (o aplicativo do celular) e pela API oficial da Meta (no modo de coexistência). No painel, esse par aparece como um único canal; na API, aparece como duas conexões que apontam uma para a outra por gemea_id. Regras que valem para a integração:

  • As duas pernas são o mesmo número. Para listar números, considere só as conexões com principal: true, como no exemplo acima.
  • Conversas novas nascem na perna principal, que é a do QR quando ela existe. O conexao_id que aparece nas conversas e nos webhooks é, em geral, o da perna principal.
  • Envio: o ChatISP escolhe a perna que vai entregar cada mensagem, como faz no painel. Se uma das pernas cair, a outra segue enviando: a chamada só responde conexao_desconectada quando as duas estão fora do ar.
  • Modelos: só a perna da API oficial envia modelos. Em mensagens/enviar_modelo e em modelos/listar, você pode informar o id de qualquer uma das pernas: o ChatISP usa a perna oficial do mesmo número.
  • Filtros: em conversas/listar, filtrar por conexao_id de qualquer perna traz as conversas do número inteiro.

Quando informar conexao_id

SituaçãoSem conexao_id
Um único número conectado (o par gêmeo conta como um número)A API usa esse número. Pode omitir.
Mais de um número conectadoA API usa o Número de origem da chave de API (Integrações, Chaves de API). Chave sem Número de origem: HTTP 400 conexao_id_obrigatorio, informe qual número usar.
Nenhum número conectadoHTTP 400 sem_conexao.
mensagens/enviar_modeloA regra acima vale só para conexões da API oficial: com um único número oficial conectado, pode omitir.
Envio para uma conversa existente (conversa_id ou protocolo)Não precisa: a mensagem sai pelo número da conversa.

Mesmo com um único número hoje, guarde o conexao_id na configuração da integração e envie-o sempre. Assim, quando o provedor conectar um segundo número (comercial, cobrança), a integração continua funcionando sem mudar nada.


Departamentos

GET /api_publica.php?r=departamentos/listar

Lista todos os departamentos, ativos e inativos, na ordem definida no painel (veja Departamentos).

Parâmetros: nenhum.

terminal
curl -s "https://atendimento.seuprovedor.com.br/api_publica.php?r=departamentos/listar" \
  -H "Authorization: Bearer $CHATISP_CHAVE"
PHP
// Mapa nome => id dos departamentos ativos
$deps = [];
foreach (chatisp('departamentos/listar')['departamentos'] as $d) {
    if ($d['ativo']) $deps[$d['nome']] = $d['id'];
}
$suporte = $deps['Suporte técnico'] ?? null;
Python
deps = {d["nome"]: d["id"] for d in chatisp("departamentos/listar")["departamentos"] if d["ativo"]}
suporte = deps.get("Suporte técnico")
resposta (HTTP 200)
{
  "ok": true,
  "departamentos": [
    { "id": 1, "nome": "Suporte técnico", "ativo": true,  "padrao": true },
    { "id": 2, "nome": "Financeiro",      "ativo": true,  "padrao": false },
    { "id": 3, "nome": "Comercial",       "ativo": true,  "padrao": false },
    { "id": 5, "nome": "Retenção",        "ativo": false, "padrao": false }
  ]
}
CampoTipoDescrição
idinteiroO departamento_id usado nas outras rotas.
nomestringNome do departamento.
ativobooleanoDepartamento inativo não recebe transferências nem atendimentos: usá-lo responde departamento_invalido. Ele aparece na lista porque conversas antigas podem estar ligadas a ele.
padraobooleanotrue no departamento que recebe as conversas novas (opção Departamento das novas conversas, em Configurações). Nenhum vem marcado quando a opção está vazia ou aponta para um departamento inativo.

Erros: só os de acesso.


Atendentes

GET /api_publica.php?r=atendentes/listar

Lista os usuários do painel em ordem alfabética, com perfil de acesso, departamentos, presença e pausa. Usuários excluídos não aparecem; usuários inativos aparecem com ativo: false.

Parâmetros: nenhum.

terminal
curl -s "https://atendimento.seuprovedor.com.br/api_publica.php?r=atendentes/listar" \
  -H "Authorization: Bearer $CHATISP_CHAVE"
PHP
// Quem do departamento 1 está online e fora de pausa agora
$livres = array_filter(chatisp('atendentes/listar')['atendentes'], fn($a) =>
    $a['ativo'] && $a['online'] && !$a['em_pausa'] && in_array(1, $a['departamentos'], true));
Python
# Quem do departamento 1 está online e fora de pausa agora
livres = [a for a in chatisp("atendentes/listar")["atendentes"]
          if a["ativo"] and a["online"] and not a["em_pausa"] and 1 in a["departamentos"]]
resposta (HTTP 200)
{
  "ok": true,
  "atendentes": [
    {
      "id": 7,
      "nome": "Ana Ribeiro",
      "perfil": "Atendente",
      "ativo": true,
      "departamentos": [1, 2],
      "online": true,
      "em_pausa": false
    },
    {
      "id": 4,
      "nome": "Carlos Mendes",
      "perfil": "Supervisor",
      "ativo": true,
      "departamentos": [1],
      "online": true,
      "em_pausa": true
    }
  ]
}
CampoTipoDescrição
idinteiroO atendente_id (transferência, abertura de atendimento, filtros) e o responsavel_id (ordens de serviço e agenda).
nomestringNome do usuário.
perfilstringNome do perfil de acesso (veja Usuários e perfis). Vazio se o usuário não tem perfil.
ativobooleanoUsuário inativo não pode receber conversas, ordens de serviço nem compromissos: usá-lo responde atendente_invalido.
departamentoslista de inteirosIds dos departamentos em que o usuário atende.
onlinebooleanoSe o usuário esteve com o painel aberto nos últimos 2 minutos.
em_pausabooleanoSe está online e com uma pausa aberta (almoço, intervalo). Sempre false para quem está offline.

Erros: só os de acesso.

Transferir pela API direto para um atendente funciona mesmo que ele esteja offline ou em pausa: a conversa fica com ele. Se a intenção é que alguém disponível pegue logo, transfira para o departamento e deixe a distribuição do ChatISP escolher.


Modelos de mensagem (API oficial)

GET /api_publica.php?r=modelos/listar

Lista os modelos de mensagem (templates) das conexões da API oficial da Meta, em ordem de nome e idioma. Modelo aprovado é o único jeito de falar com o cliente fora da janela de 24 horas. A lista reflete a última sincronização com a Meta, feita pelo botão Sincronizar com a Meta no card Modelos da conexão (veja Conexões de WhatsApp): modelo criado ou aprovado na Meta só aparece aqui depois de sincronizar.

ParâmetroTipoObrigatórioDescrição
conexao_idinteironãoSó os modelos dessa conexão. Pode ser o id de qualquer perna de um número gêmeo: a perna QR responde pelos modelos da perna oficial. Sem o parâmetro, vêm os modelos de todas as conexões.
terminal
curl -s "https://atendimento.seuprovedor.com.br/api_publica.php?r=modelos/listar&conexao_id=2" \
  -H "Authorization: Bearer $CHATISP_CHAVE"
PHP
// Só os que a API consegue enviar
$enviaveis = array_filter(chatisp('modelos/listar', ['conexao_id' => 2])['modelos'], fn($m) => $m['enviavel']);
foreach ($enviaveis as $m) {
    echo "{$m['id']}  {$m['nome']} ({$m['idioma']}): {$m['variaveis']} variável(is)\n";
}
Python
modelos = chatisp("modelos/listar", {"conexao_id": 2})["modelos"]
for m in (m for m in modelos if m["enviavel"]):
    print(m["id"], m["nome"], m["idioma"], m["variaveis"])
resposta (HTTP 200)
{
  "ok": true,
  "modelos": [
    {
      "id": 12,
      "conexao_id": 2,
      "nome": "aviso_manutencao",
      "idioma": "pt_BR",
      "categoria": "UTILITY",
      "status": "APPROVED",
      "corpo": "Olá, {{1}}! Haverá manutenção programada na sua região em {{2}}, das {{3}}. Pedimos desculpas pelo transtorno.",
      "variaveis": 3,
      "cabecalho": null,
      "enviavel": true,
      "atualizado_em": "2026-09-28T14:02:11-03:00"
    },
    {
      "id": 15,
      "conexao_id": 2,
      "nome": "fatura_disponivel",
      "idioma": "pt_BR",
      "categoria": "UTILITY",
      "status": "APPROVED",
      "corpo": "Olá, {{1}}. Sua fatura de {{2}} está disponível. Vencimento: {{3}}.",
      "variaveis": 3,
      "cabecalho": "DOCUMENT",
      "enviavel": false,
      "atualizado_em": "2026-09-28T14:02:11-03:00"
    }
  ]
}
CampoTipoDescrição
idinteiroO modelo_id de mensagens/enviar_modelo.
conexao_idinteiroA conexão da API oficial a que o modelo pertence.
nomestringNome do modelo na Meta. Também aceito em enviar_modelo pelo parâmetro modelo, com idioma.
idiomastringCódigo de idioma na Meta, por exemplo pt_BR. O mesmo nome pode existir em vários idiomas.
categoriastringCategoria na Meta: UTILITY, MARKETING ou AUTHENTICATION. Ela define o preço da conversa cobrado pela Meta.
statusstringSituação na Meta, como devolvida por ela (por exemplo APPROVED, PENDING, REJECTED). Só APPROVED pode ser enviado.
corpostringTexto do corpo, com as variáveis no formato {{1}}, {{2}}...
variaveisinteiroQuantas variáveis o corpo tem. Em enviar_modelo, a lista variaveis precisa ter esse número de valores, na ordem.
cabecalhostring ou nullTipo do cabeçalho do modelo: null (sem cabeçalho), TEXT, ou de mídia (IMAGE, VIDEO, DOCUMENT...).
enviavelbooleanotrue quando a API consegue enviar o modelo: aprovado e sem cabeçalho de mídia. Modelos com cabeçalho de mídia respondem modelo_com_midia no envio.
atualizado_emstringData da última sincronização deste modelo.

Erros:

errorHTTPQuando
conexao_invalida400O conexao_id informado não existe.
parametro_invalido400conexao_id não é um número inteiro.

Uma conexão QR sem perna oficial devolve a lista vazia, sem erro: números conectados só por QR não usam modelos.


Etiquetas

GET /api_publica.php?r=etiquetas/listar

Lista as etiquetas de conversa cadastradas no painel (veja Cadastros), na ordem definida lá.

Parâmetros: nenhum.

terminal
curl -s "https://atendimento.seuprovedor.com.br/api_publica.php?r=etiquetas/listar" \
  -H "Authorization: Bearer $CHATISP_CHAVE"
PHP
$etiquetas = array_column(chatisp('etiquetas/listar')['etiquetas'], 'id', 'nome');
// marca a conversa como "Visita técnica" sem tirar as outras etiquetas
chatisp('conversas/etiquetas', ['conversa_id' => 18342, 'adicionar' => [$etiquetas['Visita técnica']]], 'POST');
Python
etiquetas = {e["nome"]: e["id"] for e in chatisp("etiquetas/listar")["etiquetas"]}
# marca a conversa como "Visita técnica" sem tirar as outras etiquetas
chatisp("conversas/etiquetas", {"conversa_id": 18342, "adicionar": [etiquetas["Visita técnica"]]}, "POST")
resposta (HTTP 200)
{
  "ok": true,
  "etiquetas": [
    { "id": 3, "nome": "Visita técnica", "cor": "#f59e0b" },
    { "id": 1, "nome": "Cliente novo",   "cor": "#10b981" },
    { "id": 6, "nome": "Cancelamento",   "cor": "#ef4444" }
  ]
}
CampoTipoDescrição
idinteiroId usado em conversas/etiquetas e no filtro etiqueta_id de conversas/listar.
nomestringNome da etiqueta.
corstringCor em hexadecimal (#rrggbb), a mesma do painel.

Erros: só os de acesso.


Motivos de encerramento

GET /api_publica.php?r=motivos/listar

Lista os motivos de encerramento cadastrados no painel (veja Cadastros), ativos e inativos, na ordem definida lá.

Parâmetros: nenhum.

terminal
curl -s "https://atendimento.seuprovedor.com.br/api_publica.php?r=motivos/listar" \
  -H "Authorization: Bearer $CHATISP_CHAVE"
PHP
$motivos = array_column(array_filter(chatisp('motivos/listar')['motivos'], fn($m) => $m['ativo']), 'id', 'nome');
chatisp('conversas/encerrar', ['conversa_id' => 18342, 'motivo_id' => $motivos['Problema resolvido']], 'POST');
Python
motivos = {m["nome"]: m["id"] for m in chatisp("motivos/listar")["motivos"] if m["ativo"]}
chatisp("conversas/encerrar", {"conversa_id": 18342, "motivo_id": motivos["Problema resolvido"]}, "POST")
resposta (HTTP 200)
{
  "ok": true,
  "motivos": [
    { "id": 1, "nome": "Problema resolvido",  "ativo": true },
    { "id": 2, "nome": "Dúvida esclarecida",  "ativo": true },
    { "id": 4, "nome": "Cliente não respondeu", "ativo": true },
    { "id": 7, "nome": "Engano",              "ativo": false }
  ]
}
CampoTipoDescrição
idinteiroO motivo_id de conversas/encerrar.
nomestringNome do motivo. É o texto que aparece em motivo_encerramento nas conversas e no campo motivo do webhook conversa_encerrada.
ativobooleanoMotivo inativo não pode ser usado para encerrar (motivo_invalido), mas segue aparecendo nas conversas antigas.

Erros: só os de acesso.


Guardar e atualizar os catálogos

Os catálogos mudam pouco: departamentos, etiquetas e motivos só mudam quando alguém edita os cadastros no painel. Boas práticas:

  • Guarde em cache no seu sistema e atualize em intervalos (por exemplo, a cada hora) ou ao iniciar a integração. Consultar o catálogo a cada envio gasta o limite por minuto à toa.
  • Prefira ids a nomes. Nomes podem ser editados no painel a qualquer momento; o id continua o mesmo. Se a sua configuração usa nomes (como nos exemplos acima), resolva o id ao iniciar e avise quando um nome não for encontrado.
  • Trate os erros de cadastro (departamento_invalido, atendente_invalido, motivo_invalido, etiqueta_invalida) como sinal para recarregar o catálogo: algo foi desativado ou excluído no painel.
  • Presença muda o tempo todo. Os campos online e em_pausa de atendentes/listar valem para o momento da consulta; não os guarde em cache.
  • Estado da conexão também. Antes de um disparo grande, confira em conexoes/listar se o número está conectada.