Agenda

Referência das seis rotas da Agenda na API do ChatISP: consulte os tipos de compromisso, liste e consulte a agenda da equipe, marque visitas, retornos e reuniões a partir de outro sistema e registre a conclusão ou o cancelamento.

Visão geral

A Agenda do ChatISP guarda os compromissos da equipe: visita técnica, retorno de contato, instalação, reunião. Cada compromisso pode ter responsável, equipe, cliente e atendimento vinculado, e dispara sozinho os avisos ao responsável e os lembretes ao cliente pelo WhatsApp. Pela API, o seu sistema marca e acompanha esses compromissos com as mesmas regras da tela.

Casos típicos de integração:

  • ERP e ordens de serviço: a OS de instalação agendada no ERP vira compromisso na agenda do técnico, com lembrete automático ao cliente na véspera.
  • Portal do assinante: o cliente escolhe o horário da visita no portal e o compromisso nasce já com a confirmação enviada pelo WhatsApp.
  • Aplicativo de campo: o técnico vê a agenda do dia e marca a visita como concluída, com o desfecho.
  • Roteirização: um sistema externo lê a agenda da semana por equipe para planejar rotas.

Rotas

RotaMétodoPermissão da chaveO que faz
agenda/tiposGETConsultar agendaTipos de compromisso e a duração padrão de cada um.
agenda/listarGETConsultar agendaCompromissos de um período, com filtros.
agenda/consultarGETConsultar agendaUm compromisso.
agenda/criarPOSTGerenciar agendaMarca um compromisso.
agenda/concluirPOSTGerenciar agendaMarca como concluído, com desfecho.
agenda/cancelarPOSTGerenciar agendaCancela, com motivo.

As permissões são marcadas na chave, em Integrações, card API do ChatISP. Gerenciar agenda não inclui a leitura: para marcar e depois consultar, marque as duas. Autenticação, formato das chamadas, paginação e erros comuns estão na Introdução.

A chave enxerga a agenda da casa inteira, de todas as equipes e responsáveis. As regras de quem vê o quê no painel valem para as pessoas, não para a API. Compromissos marcados pela API ficam com origem igual a api e, nas notas do atendimento vinculado, a ação aparece como feita por API: <nome da chave>.


O objeto compromisso

Formato usado por todas as rotas que devolvem compromissos. Datas em ISO 8601 com o fuso do servidor.

CampoTipoDescrição
idinteiroIdentificador do compromisso.
titulotextoTítulo, até 160 caracteres.
tipoobjeto ou null{"id", "nome"} do tipo; null sem tipo.
descricaotextoObservações; vazio quando não há.
inicio / fimdataComeço e fim. Sempre em minutos cheios (os segundos são zerados).
dia_inteirobooleanotrue no compromisso de dia inteiro: inicio às 00:00 e fim às 23:59 do mesmo dia.
localtextoEndereço ou ponto de encontro.
linktextoLink da reunião (por exemplo, a sala do Google Meet criada para o compromisso).
estadotextoagendado, concluido ou cancelado.
origemtextomanual (marcado na Agenda), chat (marcado a partir de um atendimento), copiloto, ia ou api.
responsavel_id / responsavelinteiro ou null / textoPessoa responsável.
departamento_idinteiro ou nullEquipe do compromisso.
conversa_idinteiro ou nullAtendimento vinculado.
clienteobjeto{"telefone", "nome"}. Telefone com DDI, só dígitos; vazio quando o compromisso não tem cliente.
desfechotextoO que foi registrado ao concluir ou cancelar.
criado_em / atualizado_emdataCriação e última alteração do registro.
JSON (objeto compromisso)
{
  "id": 342,
  "titulo": "Visita técnica: troca de roteador",
  "tipo": {"id": 3, "nome": "Visita técnica"},
  "descricao": "Levar roteador dual band. Portão azul, interfone 2.",
  "inicio": "2026-10-02T09:00:00-03:00",
  "fim": "2026-10-02T10:00:00-03:00",
  "dia_inteiro": false,
  "local": "Rua das Palmeiras, 120, Centro",
  "link": "",
  "estado": "agendado",
  "origem": "api",
  "responsavel_id": 7,
  "responsavel": "Carlos Lima",
  "departamento_id": 3,
  "conversa_id": 5310,
  "cliente": {"telefone": "5544999990000", "nome": "Maria Souza"},
  "desfecho": "",
  "criado_em": "2026-10-01T14:20:03-03:00",
  "atualizado_em": "2026-10-01T14:20:03-03:00"
}

Estados

estadoSignificado
agendadoCompromisso vigente. Só ele dispara avisos ao responsável e lembretes ao cliente.
concluidoRealizado. Os alertas pendentes são descartados.
canceladoNão vai acontecer. Os alertas pendentes são descartados e o evento espelhado no Google Agenda é removido.

Tipos de compromisso

GET/api_publica.php?r=agenda/tipos

Devolve os tipos de compromisso cadastrados, na ordem da tela, inclusive os desativados. Sem parâmetros. O tipo define a duração padrão, as antecedências dos avisos ao responsável e dos lembretes ao cliente, e se o evento no Google Agenda nasce com sala do Meet.

Campo de tipos[]Descrição
idIdentificador, usado em tipo_id.
nomeNome do tipo.
ativofalse quando desativado.
duracao_minDuração padrão em minutos, usada para calcular o fim quando a marcação não informa fim nem duracao_min.
curl
curl -s -G "https://atendimento.seuprovedor.com.br/api_publica.php" \
  -H "Authorization: Bearer $CHATISP_CHAVE" \
  --data-urlencode "r=agenda/tipos"
PHP
<?php
$url = 'https://atendimento.seuprovedor.com.br/api_publica.php?' . http_build_query([
    'r' => 'agenda/tipos',
]);
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('CHATISP_CHAVE')],
]);
$resposta = json_decode(curl_exec($ch), true);
Python
import os, requests

resposta = requests.get(
    "https://atendimento.seuprovedor.com.br/api_publica.php",
    params={"r": "agenda/tipos"},
    headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]},
    timeout=30,
).json()
Resposta
{
  "ok": true,
  "tipos": [
    {"id": 1, "nome": "Reunião", "ativo": true, "duracao_min": 60},
    {"id": 2, "nome": "Retorno de contato", "ativo": true, "duracao_min": 15},
    {"id": 3, "nome": "Visita técnica", "ativo": true, "duracao_min": 60},
    {"id": 4, "nome": "Treinamento", "ativo": true, "duracao_min": 90},
    {"id": 5, "nome": "Apresentação", "ativo": true, "duracao_min": 60}
  ]
}

Os tipos e as antecedências de cada um são configurados pelo provedor na Agenda: veja Tipos de compromisso.


Listar compromissos

GET/api_publica.php?r=agenda/listar

Compromissos que tocam o período pedido (começam antes do fim do período e terminam depois do começo dele), em ordem de início. Um compromisso das 23:00 às 01:00 aparece tanto no dia em que começa quanto no seguinte.

ParâmetroTipoDescrição
dedataComeço do período. Padrão: hoje, 00:00.
atedataFim do período. Padrão: 30 dias depois de de, às 23:59:59. Data sem hora vale até 23:59:59 do dia. O período máximo é de 366 dias.
estadotextoagendado, concluido ou cancelado. Sem ele, todos.
responsavel_idinteiroSó os dessa pessoa.
departamento_idinteiroSó os dessa equipe.
tipo_idinteiroSó os desse tipo.
conversa_idinteiroSó os vinculados a esse atendimento.
telefonetextoSó os desse cliente (procurado com e sem o nono dígito).
pagina / limiteinteiroPaginação numerada: limite de 1 a 100 (padrão 50).
curl
curl -s -G "https://atendimento.seuprovedor.com.br/api_publica.php" \
  -H "Authorization: Bearer $CHATISP_CHAVE" \
  --data-urlencode "r=agenda/listar" \
  --data-urlencode "de=2026-10-02" \
  --data-urlencode "ate=2026-10-02" \
  --data-urlencode "responsavel_id=7" \
  --data-urlencode "estado=agendado"
PHP
<?php
$url = 'https://atendimento.seuprovedor.com.br/api_publica.php?' . http_build_query([
    'r' => 'agenda/listar',
    'de' => '2026-10-02',
    'ate' => '2026-10-02',
    'responsavel_id' => 7,
    'estado' => 'agendado',
]);
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('CHATISP_CHAVE')],
]);
$resposta = json_decode(curl_exec($ch), true);
Python
import os, requests

resposta = requests.get(
    "https://atendimento.seuprovedor.com.br/api_publica.php",
    params={"r": "agenda/listar", "de": "2026-10-02", "ate": "2026-10-02", "responsavel_id": 7, "estado": "agendado"},
    headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]},
    timeout=30,
).json()
Resposta
{
  "ok": true,
  "periodo": {"de": "2026-10-02T00:00:00-03:00", "ate": "2026-10-02T23:59:59-03:00"},
  "compromissos": [
    {
      "id": 342,
      "titulo": "Visita técnica: troca de roteador",
      "tipo": {"id": 3, "nome": "Visita técnica"},
      "inicio": "2026-10-02T09:00:00-03:00",
      "fim": "2026-10-02T10:00:00-03:00",
      "estado": "agendado",
      "local": "Rua das Palmeiras, 120, Centro",
      "cliente": {"telefone": "5544999990000", "nome": "Maria Souza"},
      "...": "demais campos do objeto compromisso"
    }
  ],
  "paginacao": {"pagina": 1, "limite": 50, "total": 1, "paginas": 1}
}

O bloco periodo devolve o período efetivamente usado, o que ajuda a conferir os padrões quando de ou ate foram omitidos.


Consultar um compromisso

GET/api_publica.php?r=agenda/consultar
ParâmetroTipoObrigatórioDescrição
idinteirosimId do compromisso.
curl
curl -s -G "https://atendimento.seuprovedor.com.br/api_publica.php" \
  -H "Authorization: Bearer $CHATISP_CHAVE" \
  --data-urlencode "r=agenda/consultar" \
  --data-urlencode "id=342"
PHP
<?php
$url = 'https://atendimento.seuprovedor.com.br/api_publica.php?' . http_build_query([
    'r' => 'agenda/consultar',
    'id' => 342,
]);
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('CHATISP_CHAVE')],
]);
$resposta = json_decode(curl_exec($ch), true);
Python
import os, requests

resposta = requests.get(
    "https://atendimento.seuprovedor.com.br/api_publica.php",
    params={"r": "agenda/consultar", "id": 342},
    headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]},
    timeout=30,
).json()
Resposta
{
  "ok": true,
  "compromisso": {"id": 342, "titulo": "Visita técnica: troca de roteador", "...": "objeto compromisso completo"}
}

Marcar um compromisso

POST/api_publica.php?r=agenda/criar

Marca um compromisso no estado agendado. Título e início são obrigatórios; o fim pode vir explícito, por duração ou pelo tipo.

ParâmetroTipoObrigatórioDescrição
titulotextosimDe 1 a 160 caracteres.
iniciodatasimData e hora de início (ISO 8601 ou AAAA-MM-DD HH:MM:SS no fuso do servidor).
fimdatanãoData e hora de término. Precisa ser depois do início.
duracao_mininteironãoDuração em minutos, usada quando fim não vem.
dia_inteirobooleanonãoCompromisso do dia todo: ocupa o dia de inicio das 00:00 às 23:59, e fim e duracao_min são ignorados.
tipo_idinteironãoTipo do compromisso (agenda/tipos). Tipo inexistente ou desativado dá tipo_invalido.
descricaotextonãoObservações, até 5.000 caracteres.
localtextonãoEndereço ou ponto de encontro, até 255 caracteres.
linktextonãoLink da reunião, começando com http:// ou https://, até 500 caracteres.
responsavel_idinteironãoPessoa responsável (ativa).
departamento_idinteironãoEquipe do compromisso.
conversa_idinteironãoAtendimento vinculado. Completa telefone e nome do cliente quando não informados.
telefonetextonãoWhatsApp do cliente, para confirmação e lembretes. Mesma regra de telefone do resto da API.
nome_clientetextonãoNome do cliente, até 190 caracteres. Vai na variável {nome} dos textos ao cliente.
confirmar_clientebooleanonãoEnvia na hora a confirmação ao cliente pelo WhatsApp. Sem o parâmetro, vale o padrão do tipo (como no formulário da tela); sem tipo, não envia. Mande false para não enviar mesmo num tipo que pede confirmação.
curl
curl -s -X POST "https://atendimento.seuprovedor.com.br/api_publica.php?r=agenda/criar" \
  -H "Authorization: Bearer $CHATISP_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{"titulo": "Visita técnica: troca de roteador", "tipo_id": 3, "inicio": "2026-10-02T09:00:00-03:00", "local": "Rua das Palmeiras, 120, Centro", "responsavel_id": 7, "departamento_id": 3, "telefone": "44999990000", "nome_cliente": "Maria Souza", "confirmar_cliente": true}'
PHP
<?php
$dados = [
    'titulo' => 'Visita técnica: troca de roteador',
    'tipo_id' => 3,
    'inicio' => '2026-10-02T09:00:00-03:00',
    'local' => 'Rua das Palmeiras, 120, Centro',
    'responsavel_id' => 7,
    'departamento_id' => 3,
    'telefone' => '44999990000',
    'nome_cliente' => 'Maria Souza',
    'confirmar_cliente' => true,
];
$ch = curl_init('https://atendimento.seuprovedor.com.br/api_publica.php?r=agenda/criar');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CHATISP_CHAVE'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($dados, JSON_UNESCAPED_UNICODE),
]);
$resposta = json_decode(curl_exec($ch), true);
Python
import os, requests

resposta = requests.post(
    "https://atendimento.seuprovedor.com.br/api_publica.php",
    params={"r": "agenda/criar"},
    headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]},
    json={"titulo": "Visita técnica: troca de roteador", "tipo_id": 3, "inicio": "2026-10-02T09:00:00-03:00", "local": "Rua das Palmeiras, 120, Centro", "responsavel_id": 7, "departamento_id": 3, "telefone": "44999990000", "nome_cliente": "Maria Souza", "confirmar_cliente": True},
    timeout=30,
).json()
Resposta
{
  "ok": true,
  "compromisso": {
    "id": 342,
    "titulo": "Visita técnica: troca de roteador",
    "inicio": "2026-10-02T09:00:00-03:00",
    "fim": "2026-10-02T10:00:00-03:00",
    "estado": "agendado",
    "origem": "api",
    "...": "demais campos do objeto compromisso"
  }
}

Como o fim é calculado

  1. Com dia_inteiro: do começo ao fim do dia de inicio.
  2. Com fim: vale o informado. Fim igual ou anterior ao início dá periodo_invalido.
  3. Com duracao_min: início mais a duração.
  4. Sem nenhum dos três: início mais a duração padrão do tipo (no mínimo 15 minutos); sem tipo, 60 minutos.

Um compromisso pode durar no máximo 30 dias.

O que acontece ao marcar

  • Alertas programados: as antecedências do aviso ao responsável e do lembrete ao cliente vêm do tipo. Sem tipo, o responsável é avisado 15 minutos antes e o cliente não recebe lembrete. Só são programados os alertas cujo horário ainda está no futuro. Detalhes em Alertas e lembretes.
  • Aviso ao responsável: a pessoa responsável recebe pelo WhatsApp "Compromisso marcado para você", com data, hora, cliente, local e link. Sem responsável, o aviso vai para a equipe do departamento. Vale para quem tem o WhatsApp verificado e os avisos ligados em Minha conta.
  • Confirmação ao cliente: com confirmar_cliente (ou, sem o parâmetro, quando o tipo pede confirmação), o cliente recebe na hora o texto de confirmação configurado em Configurações (com as variáveis {nome}, {data}, {hora}, {detalhes} e as demais). A mensagem sai pelo atendimento vinculado, pela conversa mais recente com o número ou, sem conversa nenhuma, como mensagem avulsa pelo número conectado. Com o texto de confirmação vazio em Configurações, nada é enviado. Veja Textos enviados ao cliente.
  • Google Agenda: se a pessoa responsável conectou a conta Google em Minha conta, o compromisso é espelhado na agenda Google dela; se o tipo pede sala do Google Meet e o link veio vazio, a sala é criada e o endereço entra no campo link antes da confirmação e do aviso saírem. Falha no Google nunca impede a marcação: o sistema tenta de novo em segundo plano.
  • Atendimento vinculado: com conversa_id, a linha do tempo do atendimento registra o compromisso e, se o atendimento estiver aberto, ganha uma nota interna com título, data e hora. O cliente não vê a nota.

Como na tela, onde a chave Enviar confirmação ao cliente agora já vem ligada nos tipos que pedem confirmação, a API segue o tipo quando confirmar_cliente não é enviado. Os lembretes programados pelo tipo saem normalmente, com ou sem confirmação.

A Agenda não tem eventos de webhook. Para manter um sistema externo em dia, consulte agenda/listar periodicamente pelo período que interessa.


Concluir

POST/api_publica.php?r=agenda/concluir

Marca o compromisso como realizado e registra o desfecho. Só vale para compromisso agendado; em outro estado, a resposta é 409 estado_invalido com o estado atual.

ParâmetroTipoObrigatórioDescrição
idinteirosimId do compromisso.
desfechotextonãoO que aconteceu, até 2.000 caracteres.
curl
curl -s -X POST "https://atendimento.seuprovedor.com.br/api_publica.php?r=agenda/concluir" \
  -H "Authorization: Bearer $CHATISP_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{"id": 342, "desfecho": "Roteador trocado, Wi-Fi testado com a cliente."}'
PHP
<?php
$dados = [
    'id' => 342,
    'desfecho' => 'Roteador trocado, Wi-Fi testado com a cliente.',
];
$ch = curl_init('https://atendimento.seuprovedor.com.br/api_publica.php?r=agenda/concluir');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CHATISP_CHAVE'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($dados, JSON_UNESCAPED_UNICODE),
]);
$resposta = json_decode(curl_exec($ch), true);
Python
import os, requests

resposta = requests.post(
    "https://atendimento.seuprovedor.com.br/api_publica.php",
    params={"r": "agenda/concluir"},
    headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]},
    json={"id": 342, "desfecho": "Roteador trocado, Wi-Fi testado com a cliente."},
    timeout=30,
).json()
Resposta
{
  "ok": true,
  "compromisso": {
    "id": 342,
    "estado": "concluido",
    "desfecho": "Roteador trocado, Wi-Fi testado com a cliente.",
    "...": "demais campos do objeto compromisso"
  }
}

Os alertas ainda não enviados são descartados. O atendimento vinculado registra a conclusão na linha do tempo e, se estiver aberto, ganha uma nota interna. O espelho no Google Agenda, quando existe, é sincronizado.


Cancelar

POST/api_publica.php?r=agenda/cancelar

Cancela o compromisso e registra o motivo. Só vale para compromisso agendado; em outro estado, a resposta é 409 estado_invalido com o estado atual.

ParâmetroTipoObrigatórioDescrição
idinteirosimId do compromisso.
desfechotextonãoMotivo do cancelamento, até 2.000 caracteres.
curl
curl -s -X POST "https://atendimento.seuprovedor.com.br/api_publica.php?r=agenda/cancelar" \
  -H "Authorization: Bearer $CHATISP_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{"id": 342, "desfecho": "Cliente pediu para remarcar para a próxima semana."}'
PHP
<?php
$dados = [
    'id' => 342,
    'desfecho' => 'Cliente pediu para remarcar para a próxima semana.',
];
$ch = curl_init('https://atendimento.seuprovedor.com.br/api_publica.php?r=agenda/cancelar');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CHATISP_CHAVE'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($dados, JSON_UNESCAPED_UNICODE),
]);
$resposta = json_decode(curl_exec($ch), true);
Python
import os, requests

resposta = requests.post(
    "https://atendimento.seuprovedor.com.br/api_publica.php",
    params={"r": "agenda/cancelar"},
    headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]},
    json={"id": 342, "desfecho": "Cliente pediu para remarcar para a próxima semana."},
    timeout=30,
).json()
Resposta
{
  "ok": true,
  "compromisso": {
    "id": 342,
    "estado": "cancelado",
    "desfecho": "Cliente pediu para remarcar para a próxima semana.",
    "...": "demais campos do objeto compromisso"
  }
}

Os alertas pendentes são descartados, o evento espelhado no Google Agenda é removido (e com ele a sala do Meet) e o atendimento vinculado registra o cancelamento. O cliente não recebe mensagem automática de cancelamento: se quiser avisá-lo, envie pela rota mensagens/enviar.

A API não remarca nem reabre compromissos. Para remarcar, cancele o atual e marque um novo com o horário certo; se a confirmação estiver ligada, o cliente recebe a nova data.


Erros das rotas da Agenda

Além dos erros comuns a toda a API, descritos em Erros:

errorHTTPRotasCausa
permissao403todasA chave não tem Consultar agenda (leitura) ou Gerenciar agenda (escrita). O campo escopo diz qual falta.
parametro_obrigatorio400consultar, criar, concluir, cancelarFaltou id ou inicio (veja campo).
nao_encontrado404consultar, concluir, cancelarNenhum compromisso com esse id.
tipo_invalido400criarTipo inexistente ou desativado.
estado_invalido409concluir, cancelarO compromisso não está agendado (já foi concluído ou cancelado). O campo estado traz o estado atual.
titulo_invalido400criarTítulo vazio ou com mais de 160 caracteres.
data_invalida400listar, criarData que não pôde ser lida (veja campo). Use ISO 8601 ou AAAA-MM-DD HH:MM:SS; palavras como "amanhã" não são aceitas.
periodo_invalido400listar, criarNa listagem: ate antes de de, ou período acima de 366 dias (com maximo_dias). Na marcação: fim igual ou anterior ao início.
link_invalido400criarLink que não começa com http:// ou https://, tem espaço ou passa de 500 caracteres.
telefone_invalido400listar, criarO telefone não é um número de WhatsApp válido.
parametro_invalido400listar, criarestado desconhecido (lista em aceitos), responsável ou departamento inexistente, responsável inativo, descrição acima de 5.000 caracteres, duração acima de 30 dias, número com letras, limite acima de 100.
Exemplo de erro
{"ok": false, "error": "periodo_invalido", "maximo_dias": 366}