API Externa de Agenda

Agendamento de consultas por canais externos — chatbot ChatWin no WhatsApp.

Como configurar no ChatWin

Cada rota desta API vira uma "API Externa" (uma ferramenta) no ChatWin. A IA decide sozinha quando chamar cada uma, a partir do texto da Descrição — por isso os textos prontos abaixo importam tanto quanto o código: eles vão direto para o raciocínio do modelo.

Aba do ChatWinO que preencher
Geral → Nomeo nome em snake_case indicado em cada ferramenta
Geral → Descriçãoo texto do bloco "Descrição para a IA" — copie inteiro
Conexão → MétodoPOST em todas
Conexão → URLa URL da ferramenta
Conexão → Headers customizadosIdentificador = código do cliente
AutenticaçãoBearer Token = chave de integração do cliente
Resposta → Exemploo JSON de exemplo de cada ferramenta
Parâmetrosa tabela de parâmetros de cada ferramenta
Atendente de uma unidade só: configure unidade como Query parameter fixo na aba Conexão. A IA nunca pergunta e nunca erra.
Atendente de várias unidades: configure unidade como Parâmetro, e a IA pergunta qual unidade o paciente prefere.

Autenticação

Dois headers, os dois obrigatórios em toda chamada:

Authorization: Bearer <chave de integração do cliente>
Identificador: <código do cliente>

O Identificador é o que define em qual banco a consulta roda. Ele vem da configuração da ferramenta, nunca da conversa — a IA não vê e não tem como errar de cliente.

Credencial inválida devolve 401. É o único caso, junto com 429 (limite excedido), em que a resposta não é 200.

Contrato das respostas

Toda resposta é HTTP 200, inclusive quando não deu certo. O resultado real vai no campo situacao. Isso é proposital: o ChatWin trata qualquer resposta não-2xx como "falha da ferramenta" e a IA perde o conteúdo — deixando de saber a diferença entre "está lotado", "a agenda não foi liberada" e "esse horário acabou de ser tomado".

Todas as respostas carregam estes campos:

CampoPara que serve
oktrue quando a operação deu certo
situacaoo código do resultado — é o que a IA lê para decidir o que falar
msgfrase pronta em português para a IA repassar ao paciente
hojedata de hoje na clínica (dd/mm/aaaa)
agorahora atual na clínica (hh:mm)
hoje e agora vão em toda resposta de propósito. O modelo erra data relativa ("quinta que vem", "semana que vem") com frequência, e o relógio da conversa não é o da clínica. Instrua a IA a sempre calcular datas a partir do hoje.

Situações possíveis

situacaoSignificaO que a IA deve fazer
OKdeu certoseguir normalmente
SEM_VAGAestá lotado no períodooferecer outro período
AGENDA_NAO_ABERTAa clínica ainda não liberou esse período não dizer que está lotado — dizer que ainda não abriu e oferecer avisar depois
NAO_ATENDE_NO_DIAa unidade não atende nesses diasoferecer outros dias
OCUPADOo horário foi tomado agora há pouco pedir desculpa e oferecer as alternativas que vieram junto
HORARIO_INEXISTENTEesse horário nunca existiu na grade consultar a disponibilidade de novo antes de falar
NAO_ENCONTRADOnão achou a consultaconfirmar telefone e data com o paciente
JA_FEITOjá estava nesse estadotranquilizar — está tudo certo, não é erro
AMBIGUOmais de uma consulta casa com o pedido ler as candidatas e perguntar qual antes de tentar de novo
FORA_DO_PRAZOa consulta já passouorientar a ligar para a unidade
DADOS_INVALIDOSalgum parâmetro veio erradoler a msg e corrigir
ERRO_TEMPORARIOfalha momentâneatentar de novo em alguns segundos

As 8 ferramentas

1. consultar_horarios

POST /api/Externa/AgendaOnline/ConsultarHorarios
Descrição para a IA
Consulta os horários livres para consulta em uma unidade. Use SEMPRE que o paciente quiser marcar, perguntar disponibilidade, citar um dia ("quinta", "semana que vem", "dia 3 de setembro") ou um turno ("de manhã", "de tarde"). Pode chamar sem informar data — nesse caso vêm os próximos dias que tiverem vaga. Ofereça APENAS os horários que vierem em dias[].horas; nunca invente horário. Leia o campo situacao antes de responder: SEM_VAGA significa lotado naquele período, ofereça outro; AGENDA_NAO_ABERTA significa que a clínica ainda não liberou esse período — diga isso e NÃO diga que está lotado; NAO_ATENDE_NO_DIA significa que a unidade não atende nesses dias. Use o campo hoje para calcular qualquer data relativa: é a data do sistema da clínica e é mais confiável que a sua. Se truncado vier true, existem mais horários além dos listados — diga que há mais opções caso nenhum sirva.
Parâmetros
NomeTipoObrig.Descrição (para a IA)
unidadestringsim*Código da unidade de atendimento
destringnãoPrimeiro dia do período, no formato dd/mm/aaaa
atestringnãoÚltimo dia do período, no formato dd/mm/aaaa
turnostringnãomanha, tarde ou noite

* Se o atendente cobre uma unidade só, deixe fora dos parâmetros e configure como query param fixo.

Exemplo de resposta
{
  "ok": true,
  "situacao": "OK",
  "hoje": "18/08/2026",
  "agora": "14:32",
  "unidade": { "id": "1", "nome": "OTICA CENTRO" },
  "dias": [
    { "data": "20/08/2026", "semana": "quinta-feira", "horas": ["09:00","09:30","14:00"] },
    { "data": "22/08/2026", "semana": "sábado", "horas": ["08:00"] }
  ],
  "total": 12,
  "truncado": true,
  "msg": "Tenho 3 horários na quinta-feira (20/08/2026) e mais opções nos dias seguintes."
}

2. proximo_horario_livre

POST /api/Externa/AgendaOnline/ProximoHorario
Descrição para a IA
Devolve as primeiras vagas disponíveis, varrendo para frente a partir de agora. Use quando o paciente não tiver data em mente ou pedir "o mais cedo possível", "qualquer dia", "o quanto antes", "o primeiro que tiver". Prefira esta ferramenta em vez de consultar_horarios sempre que não houver data na conversa: ela é mais rápida e já vem ordenada da mais próxima para a mais distante. Ofereça as opções na ordem em que vierem, começando pela primeira.
Parâmetros
NomeTipoObrig.Descrição (para a IA)
unidadestringsim*Código da unidade de atendimento
turnostringnãomanha, tarde ou noite
quantidadenúmeronãoQuantas opções devolver (padrão 3)
Exemplo de resposta
{
  "ok": true,
  "situacao": "OK",
  "hoje": "18/08/2026",
  "agora": "14:32",
  "unidade": { "id": "1", "nome": "OTICA CENTRO" },
  "opcoes": [
    { "data": "20/08/2026", "semana": "quinta-feira", "hora": "09:00", "em_dias": 2 },
    { "data": "20/08/2026", "semana": "quinta-feira", "hora": "09:30", "em_dias": 2 }
  ],
  "msg": "A vaga mais próxima é quinta-feira, dia 20/08/2026, às 09:00."
}

3. agendar_consulta

POST /api/Externa/AgendaOnline/Agendar
Descrição para a IA
Marca a consulta em um horário livre. Só chame depois de ter com certeza: unidade, data, hora, nome completo do paciente e telefone. A hora precisa ser exatamente uma das devolvidas por consultar_horarios ou proximo_horario_livre. Guarde o campo referencia da resposta — é com ele que você cancela, confirma ou remarca depois, sem precisar perguntar data e hora de novo. Se situacao vier OCUPADO, o horário foi tomado por outra pessoa: peça desculpa e ofereça imediatamente o que vier em alternativas, não repita a chamada com os mesmos dados. Se vier HORARIO_INEXISTENTE, esse horário nunca existiu: consulte a disponibilidade de novo antes de falar. Se vier JA_FEITO, essa consulta já estava marcada — apenas confirme ao paciente, não é erro. Se o paciente estiver marcando para outra pessoa (filho, mãe, cônjuge), coloque o nome DELA em nome e mantenha o telefone do WhatsApp.
Parâmetros
NomeTipoObrig.Descrição (para a IA)
unidadestringsim*Código da unidade de atendimento
datastringsimData da consulta, no formato dd/mm/aaaa
horastringsimHorário da consulta, no formato hh:mm
nomestringsimNome completo de quem será atendido
telefonestringsimTelefone do WhatsApp do paciente, com DDD
Exemplo de resposta
{
  "ok": true,
  "situacao": "OK",
  "hoje": "18/08/2026",
  "agora": "14:32",
  "referencia": "48211",
  "data": "20/08/2026",
  "semana": "quinta-feira",
  "hora": "09:00",
  "unidade": { "id": "1", "nome": "OTICA CENTRO" },
  "alternativas": [],
  "msg": "Consulta marcada para quinta-feira, 20/08/2026, às 09:00."
}
Quando o horário é tomado no meio do caminho, a resposta já traz as alternativas do mesmo dia — a IA oferece na mesma frase, sem precisar de outra chamada.

4. minhas_consultas

POST /api/Externa/AgendaOnline/MinhasConsultas
Descrição para a IA
Lista as consultas já marcadas do paciente, pelo telefone do WhatsApp. Use antes de cancelar, confirmar ou remarcar sempre que o paciente não disser a data com clareza — e também para responder "que horas é minha consulta?", "quando eu marquei?", "tenho consulta marcada?". Inclui a consulta de hoje mesmo que o horário já tenha passado há pouco. Se vier mais de uma, leia os nomes para o paciente e pergunte de qual ele está falando, porque um mesmo telefone pode ter consultas de pessoas diferentes da família. Use o campo referencia de cada item nas ferramentas de cancelar, confirmar e remarcar.
Parâmetros
NomeTipoObrig.Descrição (para a IA)
telefonestringsimTelefone do WhatsApp do paciente, com DDD
unidadestringnãoCódigo da unidade, para filtrar
Exemplo de resposta
{
  "ok": true,
  "situacao": "OK",
  "hoje": "18/08/2026",
  "agora": "14:32",
  "consultas": [
    { "referencia": "48211", "paciente": "MARIA SOUZA", "data": "20/08/2026",
      "semana": "quinta-feira", "hora": "09:00", "situacao": "AGENDADO",
      "unidade": { "id": "1", "nome": "OTICA CENTRO" }, "hoje_mesmo": false }
  ],
  "total": 1,
  "msg": "Encontrei 1 consulta."
}

5. cancelar_consulta

POST /api/Externa/AgendaOnline/Cancelar
Descrição para a IA
Cancela uma consulta já marcada e devolve o horário para a agenda. Prefira SEMPRE passar a referencia que veio de minhas_consultas ou de agendar_consulta. Só use data e hora quando não tiver a referência — e nesse caso informe também a hora, nunca só a data. Se o paciente tiver mais de uma consulta compatível, a resposta vem com situacao AMBIGUO e a lista em candidatas: pergunte qual antes de tentar de novo e NUNCA cancele todas por conta própria. JA_FEITO significa que essa consulta já não estava mais marcada — tranquilize o paciente, está tudo certo. FORA_DO_PRAZO significa que a consulta já aconteceu: oriente o paciente a ligar para a unidade.
Parâmetros
NomeTipoObrig.Descrição (para a IA)
telefonestringsimTelefone do WhatsApp do paciente, com DDD
referenciastringnãoCódigo da consulta devolvido antes (preferido)
datastringnãoData da consulta, dd/mm/aaaa (use só sem a referência)
horastringnãoHorário da consulta, hh:mm (use junto com a data)
motivostringnãoMotivo do cancelamento, se o paciente disser
Exemplo — ambiguidade
{
  "ok": false,
  "situacao": "AMBIGUO",
  "hoje": "18/08/2026",
  "candidatas": [
    { "referencia": "48211", "paciente": "MARIA SOUZA", "hora": "09:00", "data": "20/08/2026" },
    { "referencia": "48219", "paciente": "ANA SOUZA",   "hora": "09:30", "data": "20/08/2026" }
  ],
  "msg": "Encontrei 2 consultas nesse dia. Qual delas?"
}

6. confirmar_consulta

POST /api/Externa/AgendaOnline/Confirmar
Descrição para a IA
Registra que o paciente confirmou a presença na consulta. Use quando ele responder "sim", "confirmado", "estarei lá", "pode confirmar" a um lembrete, ou quando confirmar espontaneamente. Prefira passar a referencia. Se situacao vier JA_FEITO, a presença já estava confirmada — apenas tranquilize o paciente, não trate como erro. Se vier AMBIGUO, pergunte de qual consulta ele está falando antes de tentar de novo.
Parâmetros

Os mesmos de cancelar_consulta, sem o motivo.

Exemplo de resposta
{
  "ok": true,
  "situacao": "OK",
  "hoje": "18/08/2026",
  "referencia": "48211",
  "data": "20/08/2026",
  "semana": "quinta-feira",
  "hora": "09:00",
  "paciente": "MARIA SOUZA",
  "unidade": { "id": "1", "nome": "OTICA CENTRO" },
  "msg": "Presença confirmada para quinta-feira, 20/08/2026, às 09:00."
}

7. remarcar_consulta

POST /api/Externa/AgendaOnline/Remarcar
Descrição para a IA
Muda uma consulta já marcada para outro dia ou horário, em uma única operação. Use SEMPRE que o paciente quiser adiar, antecipar, "mudar", "trocar" ou "passar para outro dia". NUNCA cancele e marque de novo separadamente: se o horário novo não estiver mais livre, o paciente ficaria sem consulta nenhuma. Passe a referencia da consulta atual e o novo dia e horário. Se situacao vier OCUPADO, a consulta ANTIGA continua de pé — diga isso claramente ao paciente e ofereça o que vier em alternativas.
Parâmetros
NomeTipoObrig.Descrição (para a IA)
telefonestringsimTelefone do WhatsApp do paciente, com DDD
referenciastringnãoCódigo da consulta atual (preferido)
datastringnãoData da consulta ATUAL (use só sem a referência)
horastringnãoHorário da consulta ATUAL
nova_datastringsimNova data, no formato dd/mm/aaaa
nova_horastringsimNovo horário, no formato hh:mm
Exemplo — horário novo indisponível
{
  "ok": false,
  "situacao": "OCUPADO",
  "hoje": "18/08/2026",
  "mantida": { "data": "20/08/2026", "semana": "quinta-feira", "hora": "09:00", "em_dias": 2 },
  "alternativas": [ { "data": "27/08/2026", "hora": "14:30", "em_dias": 9 } ],
  "msg": "O horário novo não está mais livre. Sua consulta de 20/08/2026 às 09:00 continua marcada."
}
Esta ferramenta ocupa o horário novo antes de liberar o antigo. Se o novo falhar, nada é alterado e o paciente continua com a consulta original.

8. listar_unidades

POST /api/Externa/AgendaOnline/Unidades
Descrição para a IA
Lista as unidades de atendimento com endereço e telefone. Use quando o paciente não disser onde quer ser atendido, perguntar "onde vocês ficam", "qual o endereço", "tem alguma perto de mim", ou citar um bairro ou cidade. Use o campo id da unidade escolhida nas demais ferramentas. Repasse o endereço exatamente como vier, sem abreviar e sem completar de cabeça. Se houver só uma unidade, não pergunte nada: siga direto com ela.
Parâmetros
NomeTipoObrig.Descrição (para a IA)
buscastringnãoBairro, cidade ou nome da unidade que o paciente citou
unidadestringnãoCódigo de uma unidade específica
Exemplo de resposta
{
  "ok": true,
  "situacao": "OK",
  "hoje": "18/08/2026",
  "unidades": [
    { "id": "1", "nome": "OTICA CENTRO", "endereco": "RUA OLEGARIO MACIEL 100",
      "bairro": "CENTRO", "cidade": "UBERLANDIA", "uf": "MG",
      "cep": "38400000", "fone": "34 32320000" }
  ],
  "total": 1
}

Limites de uso

Dois limites independentes, ambos por minuto:

LimitePadrãoAplicado a
Por endereço IP120/mintodas as chamadas, antes da autenticação
Consulta, por cliente60/minconsultar_horarios, proximo_horario_livre, minhas_consultas, listar_unidades
Escrita, por cliente20/minagendar, cancelar, confirmar, remarcar

Ao estourar, a resposta é 429 com o header Retry-After em segundos, e o corpo no mesmo formato das demais (situacao: ERRO_TEMPORARIO). Os limites são ajustáveis por cliente na configuração da API.

Cuidado com repetição. Se uma chamada de escrita não responder, a IA não deve repetir em sequência. agendar_consulta é seguro repetir (devolve JA_FEITO), mas cancelar e remarcar não são — repetir pode devolver NAO_ENCONTRADO mesmo tendo funcionado na primeira vez.

Referência técnica

A especificação navegável, com todos os campos e a possibilidade de testar cada rota informando a credencial, está em /swagger.