Agenda VetAgenda Vet

Documentação da API do Agente

Como um agente de IA (ex.: no n8n) usa a API do Agenda Vet como ferramentas para consultar a agenda, marcar consultas e responder o cliente no WhatsApp.

Visão geral

  • Base URLhttps://agendamento.btwdata.tech
  • AutenticaçãoAuthorization: Bearer <API_KEY> em toda chamada.
  • FormatoJSON no request e na resposta. Datas em ISO 8601 com fuso (ex.: 2026-07-20T14:30:00-03:00).
  • IsolamentoA clínica é resolvida a partir da API key no servidor. Um agente nunca enxerga outra clínica.

1. Gerar a API key

No app, como Gestor: Configurações → Agente de IA → Nova chave.

  • A chave aparece uma única vez (guarde na hora); o sistema guarda só o hash.
  • Marque "Pode marcar consultas" para permitir escrita; sem isso, a chave é somente leitura (rotas de escrita respondem 403).
  • Para revogar, apague a chave na mesma tela. Formato: vet_live_XXalgo.

2. Autenticação no n8n

Guarde a chave numa credencial, nunca em texto no nó:

  1. n8n → Credentials → New → Header Auth.
  2. Name: Agenda Vet
  3. Header Name: Authorization
  4. Header Value: Bearer vet_live_XXalgo
  5. Use essa credencial em todo nó HTTP Request que chamar a API.

3. Usar como ferramenta do AI Agent

No nó AI Agent, cada rota vira uma tool. Use o nó HTTP Request Tool (um por rota) e deixe o modelo preencher os parâmetros com $fromAI(...):

{{ $fromAI('doctorId', 'ID do doutor escolhido', 'string') }}

Em cada tool: Authentication = Header Auth (credencial Agenda Vet); URL = base + caminho da rota; e cole a "Descrição para o modelo" de cada rota abaixo no campo de descrição da tool.

4. Rotas (as ferramentas)

GET/api/agent/doctors

Listar doutores e escala

Quem existe, do que entende e quando atende. Leia isto antes de sugerir horário. Retorna também o fuso e a duração da consulta da clínica.

Resposta
{
  "clinica": { "fuso": "America/Sao_Paulo", "duracaoConsultaMin": 30 },
  "doutores": [
    {
      "id": "ckdoc123",
      "nome": "Dra. Ana Paula",
      "especialidade": "Clínica Geral",
      "especialidadeId": "ckspec1",
      "crmv": "SP-12345",
      "cor": "#C9A961",
      "escala": [
        { "weekday": 1, "dia": "segunda", "inicio": "09:00", "fim": "12:00" }
      ]
    }
  ]
}
Descrição para o modelo

Lista os doutores da clínica, especialidades e a escala semanal. Use no início para saber quem pode atender.

GET/api/agent/availability

Horários livres

Slots já descontados de escala, bloqueios (férias/feriado), consultas existentes e passado.

Parâmetros
  • from(ISO 8601, opcional)Início da busca. Padrão: agora.
  • to(ISO 8601, opcional)Fim da busca. Padrão: +7 dias. Máx. 60 dias.
  • doctorId(string, opcional)Restringe a um doutor.
  • specialtyId(string, opcional)Restringe a uma especialidade.
Resposta
{
  "de": "2026-07-20T00:00:00.000Z",
  "ate": "2026-07-27T00:00:00.000Z",
  "fuso": "America/Sao_Paulo",
  "duracaoConsultaMin": 30,
  "doutores": [
    {
      "doctorId": "ckdoc123",
      "nome": "Dra. Ana Paula",
      "especialidade": "Clínica Geral",
      "horariosLivres": [
        { "inicio": "2026-07-20T12:00:00.000Z", "fim": "2026-07-20T12:30:00.000Z" }
      ]
    }
  ]
}
Descrição para o modelo

Retorna os horários livres para marcar. Filtre por doutor ou especialidade. Use antes de agendar.

GET/api/agent/patients

Achar paciente

Localiza pet/tutor por nome ou telefone, para pegar o petId antes de marcar.

Parâmetros
  • q(string)Nome do pet, nome do tutor ou telefone.
Resposta
{
  "pacientes": [
    {
      "petId": "ckpet1",
      "nome": "Rex",
      "especie": "Cão",
      "raca": "SRD",
      "tutor": { "id": "cktut1", "nome": "Ana Paula", "telefone": "5511999998888" }
    }
  ]
}
Descrição para o modelo

Busca pacientes (pet + tutor) por nome ou telefone. Use para achar o petId antes de marcar, se o cliente já existe.

GET/api/agent/appointments

Consultas agendadas

Lista as consultas do período. Use para conferir a agenda ou achar o id de uma consulta a remarcar/cancelar.

Parâmetros
  • from(ISO 8601, opcional)Padrão: agora.
  • to(ISO 8601, opcional)Padrão: +30 dias. Máx. 90 dias.
  • doctorId(string, opcional)Restringe a um doutor.
Resposta
{
  "agendamentos": [
    {
      "id": "ckappt1",
      "inicio": "2026-07-20T12:00:00.000Z",
      "fim": "2026-07-20T12:30:00.000Z",
      "status": "AGENDADO",
      "motivo": "Vacina",
      "criadoPor": "AGENTE",
      "doutor": { "id": "ckdoc123", "nome": "Dra. Ana Paula" },
      "pet": { "id": "ckpet1", "nome": "Rex", "especie": "Cão" },
      "tutor": { "id": "cktut1", "nome": "Ana Paula", "telefone": "5511999998888" }
    }
  ]
}
Descrição para o modelo

Lista as consultas já marcadas no período. Use para conferir agenda ou achar o id de uma consulta a remarcar/cancelar.

POST/api/agent/appointmentsrequer escrita

Marcar consulta

Passe petId se já conhece o paciente; senão passe tutor + pet, que o sistema acha pelo telefone/nome ou cria na hora. Os campos extras (CPF, endereço, sexo, nascimento, peso, microchip, cor) são opcionais e enriquecem a ficha para o prontuário/termo.

Corpo (body)
{
  "doctorId": "ckdoc123",
  "inicio": "2026-07-20T12:00:00-03:00",
  "motivo": "Vacina (opcional)",
  "petId": "ckpet1"
}

// ou, sem petId (cria o paciente na hora):
{
  "doctorId": "ckdoc123",
  "inicio": "2026-07-20T12:00:00-03:00",
  "tutor": {
    "nome": "Ana Paula", "telefone": "5511999998888",
    "cpf": "000.000.000-00", "endereco": "Rua X, 123 - São Paulo/SP"
  },
  "pet": {
    "nome": "Rex", "especie": "Cão", "raca": "SRD",
    "sexo": "M", "nascimento": "2021-05-10", "pesoKg": 12.5,
    "microchip": "981000000000000", "corPelagem": "Caramelo"
  }
}
Resposta
{
  "ok": true,
  "agendamento": {
    "id": "ckappt2", "inicio": "...", "fim": "...",
    "doctorId": "ckdoc123", "petId": "ckpet1"
  }
}
Descrição para o modelo

Marca a consulta. Passe petId se conhece o paciente; senão passe tutor + pet (campos extras opcionais: cpf, endereco, sexo, nascimento AAAA-MM-DD, pesoKg, microchip, corPelagem). inicio deve ser um horário livre retornado por availability.

PATCH/api/agent/appointments/{id}requer escrita

Remarcar / mudar status

Mande só o que muda. Status válidos: AGENDADO, CONFIRMADO, ATENDIDO, FALTOU, CANCELADO.

Corpo (body)
{
  "inicio": "2026-07-21T15:00:00-03:00",
  "doctorId": "ckdoc999",
  "status": "CONFIRMADO",
  "motivo": "texto (opcional)"
}
Resposta
{
  "ok": true,
  "agendamento": { "id": "ckappt2", "inicio": "...", "fim": "...", "status": "CONFIRMADO", "doctorId": "ckdoc999" }
}
Descrição para o modelo

Edita uma consulta existente: remarcar horário, trocar doutor ou mudar status. Use o id de appointments.

DELETE/api/agent/appointments/{id}requer escrita

Cancelar consulta

Cancelamento soft (status CANCELADO): preserva o histórico e libera o horário para reagendar. Sem body.

Resposta
{ "ok": true, "cancelado": "ckappt2" }
Descrição para o modelo

Cancela a consulta e libera o horário.

GET/api/agent/inbox/status

Estado da IA na conversa

Antes de responder, confira se a IA ainda está ligada para aquele contato (a equipe pode ter assumido).

Parâmetros
  • telefone(string)Com DDI, ex.: 5511999998888.
Resposta
{
  "conversaId": "ckconv1",
  "telefone": "5511999998888",
  "iaAtiva": true,
  "motivo": null,
  "alteradaEm": null,
  "alteradaVia": null
}
Descrição para o modelo

Consulta se a IA está ativa para o telefone. Se iaAtiva for false, NÃO responda: um humano assumiu.

POST/api/agent/inbox/messagesrequer escrita

Responder no WhatsApp

Único caminho para a IA responder. Se a IA estiver desligada na conversa, o envio é recusado (409 IA_DESLIGADA).

Corpo (body)
{ "telefone": "5511999998888", "text": "Olá! Podemos marcar o banho do Rex." }
Resposta
{
  "ok": true,
  "conversaId": "ckconv1",
  "mensagem": { "id": "ckmsg1", "externalId": "wa123", "texto": "Olá!", "enviadaEm": "..." }
}
Descrição para o modelo

Envia uma mensagem de texto ao cliente pelo WhatsApp da clínica. Só funciona se a IA estiver ligada na conversa.

POST/api/agent/inbox/handoffrequer escrita

Transferir para humano

Desliga a IA e entrega a conversa para a equipe. O agente não consegue se reativar depois.

Corpo (body)
{ "telefone": "5511999998888", "motivo": "cliente pediu humano (opcional)" }
Resposta
{ "ok": true, "conversaId": "ckconv1", "iaAtiva": false, "desligadaEm": "..." }
Descrição para o modelo

Transfere a conversa para um atendente humano quando não souber resolver ou o cliente pedir. Depois disso, pare de responder.

5. Gatilho: receber a mensagem (webhook)

Para o agente reagir a mensagens que chegam no Inbox, configure em Configurações → Agente de IA → Webhook do agente a URL de um nó Webhook do n8n. A cada mensagem nova do cliente (com a IA ligada na conversa), o app faz um POST com este corpo:

{
  "clinicId": "ckclinic1",
  "conversation": { "id": "ckconv1" },
  "contact": { "number": "5511999998888", "name": "Ana Paula" },
  "message": { "text": "quero marcar banho pro Rex", "mediaType": null, "timestamp": "..." },
  "replyApi": "/api/agent/inbox/messages"
}

Cada requisição leva o header X-Signature (HMAC) para o n8n validar a origem, se quiser. O segredo de assinatura é gerenciado pelo administrador da plataforma. Fluxo típico: Webhook recebe → AI Agent decide (checa status → busca horários → marca) → HTTP Request Tool POST /api/agent/inbox/messages responde.

6. Códigos de erro

Erros têm o formato { "erro": "...", "codigo": "OPCIONAL" }.

HTTPCódigoSignificado
400-Dados inválidos (veja detalhes) ou data fora do formato ISO 8601
401-API key ausente, inválida ou inativa
403-A key é somente leitura (marque "Pode marcar consultas")
404-Recurso não encontrado nesta clínica (doutor, pet, consulta ou conversa)
409SLOT_INDISPONIVELHorário fora da escala, bloqueado ou no passado
409SLOT_OCUPADOO horário acabou de ser ocupado por outra pessoa
409IA_DESLIGADAA IA foi desligada nessa conversa (um humano assumiu)
409ENVIO_EM_ANDAMENTOOutro envio da mesma conversa está em curso; tente de novo
429-Limite de requisições excedido
503-WhatsApp não configurado ou integração pausada

7. Limites e boas práticas

Rate limit por API key, por minuto: inbox/status 600, inbox/messages 120, inbox/handoff 120. Ao receber 429, aguarde e tente de novo.

  • Comece por GET /api/agent/doctors para pegar o fuso e a duração da consulta.
  • Sempre confira horários livres (availability) antes de marcar; nunca invente um horário.
  • Antes de responder, cheque inbox/status; se iaAtiva=false, silencie.
  • Quando não souber resolver ou o cliente pedir, use handoff e pare de responder.
  • Guarde a API key numa credencial do n8n; nunca a exponha em nós ou logs.