Endpoints OTIMUS¶
A API OTIMUS usada pela AgentProIA expõe 4 endpoints essenciais. Todos
são POST (mesmo os "de leitura"), retornam JSON com envelope {"data": ...}
e aceitam os headers definidos em Autenticação.
| # | Endpoint | Método | Uso |
|---|---|---|---|
| 1 | /api/v1/agendamento/horarios |
POST | Consultar / verificar horários disponíveis |
| 2 | /api/v1/cadastros/pacientes/cpf/{cpf} |
POST | Buscar paciente por CPF |
| 3 | /api/v1/paciente/multiplos |
POST | Cadastrar novo(s) paciente(s) em lote |
| 4 | /api/v1/agendamento/agendamento |
POST | Confirmar / criar agendamento |
Regra do envelope
Toda resposta OTIMUS segue o shape {"data": X}. X pode ser:
- lista de dias com agendas/horários (endpoint 1)
- dict com campos do paciente (endpoint 2 sucesso)
- string de erro amigável (endpoint 2 falha:
"O CPF informado não foi encontrado.") - dict com
description/preparo(endpoint 4 sucesso)
1. POST /api/v1/agendamento/horarios¶
Retorna, para um filtro (agenda + convênio + procedimento + intervalo de datas), as datas e horários disponíveis na agenda do médico.
Request¶
{
"filter": {
"agendas": [{"id": 58, "tipo": "cs"}],
"convenio_id": 212,
"data": "2026-04-14",
"endDate": "2026-07-13",
"suceder": 0,
"especialidade_id": 129,
"limit": 100,
"ordenacao": "asc",
"procedimentos": [170]
}
}
Campos:
| Campo | Tipo | Notas |
|---|---|---|
filter.agendas[].id |
int | ID da agenda do médico na clínica |
filter.agendas[].tipo |
string | Literal "cs" (consulta). Não descobrimos outros valores. |
filter.convenio_id |
int | ID do convênio |
filter.data |
string | Data inicial em ISO YYYY-MM-DD |
filter.endDate |
string | Data final YYYY-MM-DD. Recomenda-se data + 90 dias |
filter.suceder |
int | Sempre 0 nos dois projetos |
filter.especialidade_id |
int | ID da especialidade |
filter.limit |
int | 100 tem sido suficiente |
filter.ordenacao |
string | "asc" (Clinfeto) ou "desc" (Medcenter) |
filter.procedimentos |
list[int] | Lista de IDs de procedimento |
Response (sucesso)¶
{
"data": [
{
"data": "15-04-2026",
"agendas": [
{
"agendaNome": "JOANA SILVA",
"horarios": [
{"hora": "14:00", "dataconsulta": "..."},
{"hora": "14:30", "dataconsulta": "..."}
]
}
]
}
]
}
Formato de data no response
A request vai em YYYY-MM-DD, mas o response volta em DD-MM-YYYY.
Trate isso no parser. O campo data do item é dia (não datetime).
Response (falha / vazio)¶
{"data": []}→ agenda sem disponibilidade (ou filtro errado).- 4xx/5xx → erro de autenticação/validação/infra.
Validações obrigatórias no cliente¶
agendaNomebate com o médico pedido. O OTIMUS às vezes retorna outras agendas; valide pelo primeiro nome do médico (ver Resolver médico).- Descarte dias no passado e horários de hoje já passados (timezone
America/Sao_Paulo). - Selecione N primeiros dias com disponibilidade — típico: 5 dias, 2 manhã
- 2 tarde. Ver Filtragem de slots.
2. POST /api/v1/cadastros/pacientes/cpf/{cpf}¶
Busca paciente por CPF. Note que o CPF vai na URL, não no body.
Request¶
Sem body (alguns clientes mandam {}, funciona também).
Response — paciente encontrado¶
{
"data": {
"id": 42,
"paciente_id": 42,
"nome": "MARIA DA SILVA",
"cpf": "12345678900",
"dataNascimento": "10-05-1985",
"celular": "5599999999999"
}
}
Response — paciente NÃO encontrado¶
Idiossincrasia
O OTIMUS retorna 200 OK mesmo quando não encontra. O campo data muda
de dict para string. O parser precisa detectar essa variante:
CPF — formato¶
Sempre enviar apenas dígitos (11 chars). Normalizar antes:
3. POST /api/v1/paciente/multiplos¶
Cadastra um ou mais pacientes em lote.
Request¶
{
"pacientes": [
{
"id": 123,
"nome": "MARIA DA SILVA",
"dataNascimento": "1985-05-10",
"cpf": "12345678900",
"celular": "5599999999999"
}
]
}
Campo id: 123 nos projetos atuais
Tanto MEDCENTER quanto CLINFETO mandam "id": 123 hardcoded. Parece que
o OTIMUS ignora e gera um ID real, mas isso não é contrato — pode quebrar
no futuro. Idealmente enviar sem o campo ou com 0/null.
Formato dos campos¶
| Campo | Formato | Exemplo |
|---|---|---|
nome |
string livre | "MARIA..." |
dataNascimento |
YYYY-MM-DD |
"1985-05-10" |
cpf |
apenas dígitos | "12345678900" |
celular |
apenas dígitos, c/ DDI | "5599999999999" |
Response¶
Tem variado entre instâncias OTIMUS. O padrão defensivo é:
- Enviar o POST.
- Não confiar no response do cadastro — imediatamente fazer
_buscar_paciente_cpf(cpf)e usar opaciente_idretornado.
Ver Cadastro de paciente.
4. POST /api/v1/agendamento/agendamento¶
Cria o agendamento em si.
Request¶
{
"paciente_id": 42,
"cpf": "12345678900",
"convenio_id": 212,
"data": "15-04-2026",
"hora": "14:00",
"agenda_id": 58,
"agenda_tipo": "cs",
"status": "ativo",
"servicos": [{"id": 170}]
}
Formato de data aqui é DD-MM-YYYY
Diferente do endpoint 1 (que usa YYYY-MM-DD no request!). Mantenha um
helper _yyyymmdd_to_ddmmyyyy().
Campos:
| Campo | Tipo | Notas |
|---|---|---|
paciente_id |
int | Obtido do endpoint 2 |
cpf |
string | Apenas dígitos |
convenio_id |
int | ID do convênio |
data |
string | DD-MM-YYYY |
hora |
string | HH:MM 24h |
agenda_id |
int | ID da agenda do médico |
agenda_tipo |
string | "cs" |
status |
string | "ativo" |
servicos |
list | [{"id": <procedimento_id>}] |
Response (sucesso)¶
{
"description": "Consulta agendada com sucesso",
"preparo": "Comparecer 15 minutos antes, trazer documento..."
}
O campo preparo varia por procedimento. Inclua ambos na mensagem que o
agente devolve ao paciente.
Resumo em uma página¶
flowchart TD
A[Paciente diz:<br/>Quero agendar USG com Joana, particular] --> B{Resolver IDs}
B --> C[agenda_id=58<br/>especialidade_id=129<br/>procedimento_id=170<br/>convenio_id=212]
C --> D[POST /agendamento/horarios]
D --> E{Slots?}
E -->|não| X[FALHA_CONSULTA]
E -->|sim| F[Agente oferece até 5 dias x 4 slots]
F --> G[Paciente escolhe + fornece nome/CPF/nasc]
G --> H[POST /cadastros/pacientes/cpf/CPF]
H --> I{Existe?}
I -->|não| J[POST /paciente/multiplos]
J --> H
I -->|sim| K[POST /agendamento/agendamento]
K --> L[Retorna description + preparo]
L --> M[Agente confirma ao paciente]