API Reference v2.0
Documentação completa de todos os endpoints — 15 módulos
Base URL:
Auth Admin:
Auth Paciente:
Rotas Compartilhadas: especialidades, medicos, unidades, slots/disponiveis, backlog (aceitam ambos tokens)
https://command-agenda-api.devsantos.workers.dev/apiAuth Admin:
Authorization: Bearer {jwt_admin} — Sessão 8hAuth Paciente:
Authorization: Bearer {jwt_paciente} — Sessão 24hRotas Compartilhadas: especialidades, medicos, unidades, slots/disponiveis, backlog (aceitam ambos tokens)
Autenticação Admin 6 endpoints
POST
/auth/login
Autenticar usuário administrativo
Request Body
{
"email": "admin@barueri.sp.gov.br",
"senha": "MinhaSenh@123"
}
Response 200
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"usuario": {
"id": 1,
"nome": "Administrador",
"email": "admin@barueri.sp.gov.br",
"role": "administrador_master",
"cargo": "Gestor de TI"
}
}
Cria sessão em ca_sessao com JTI. Token expira em 8h.
POST
/auth/logout
Encerrar sessão (revogar JWT)
Auth Required
Headers
Authorization: Bearer {token}
Response 200
{ "message": "Logout realizado com sucesso" }
Marca sessão como inativa no banco. Token fica revogado.
GET
/auth/me
Obter dados do usuário logado
Auth Required
Response 200
{
"id": 1,
"nome": "Administrador",
"email": "admin@barueri.sp.gov.br",
"cpf": "12345678901",
"cargo": "Gestor de TI",
"role": "administrador_master"
}
POST
/auth/validate-first-access
Validar token de primeiro acesso
Request Body
{ "token": "abc123def456..." }
Response 200
{
"valid": true,
"email": "novo.usuario@barueri.sp.gov.br",
"nome": "Novo Usuário"
}
POST
/auth/first-access
Definir nova senha (primeiro acesso)
Request Body
{
"token": "abc123def456...",
"email": "novo.usuario@barueri.sp.gov.br",
"senhaTemporaria": "temp123",
"novaSenha": "MinhaSenh@Segura123"
}
Requisitos: mín. 10 chars, maiúscula, minúscula, número e símbolo.
Response 200
{ "message": "Senha definida com sucesso" }
POST
/auth/resend-first-access
Reenviar e-mail de primeiro acesso
Auth Required
Request Body
{ "usuarioId": 5 }
Response 200
{ "message": "E-mail reenviado com sucesso" }
Gera novo token e senha temporária, envia via Mailjet.
Autenticação Paciente 4 endpoints
POST
/auth/paciente/login
Login do paciente (CPF + senha)
Request Body
{
"cpf": "12345678901",
"senha": "minha_senha"
}
Response 200
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"paciente": {
"id": 1,
"nome": "José da Silva",
"cpf": "12345678901",
"tipo": "Comum"
}
}
Token JWT com 24h de validade. Sessão em ca_sessao_paciente.
POST
/auth/paciente/register
Cadastrar novo paciente
Request Body
{
"nomeCompleto": "Maria Oliveira",
"cpf": "98765432100",
"senha": "senha123",
"dataNascimento": "1990-05-15",
"telefone": "(11) 98765-4321",
"email": "maria@email.com"
}
Response 201
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"paciente": {
"id": 10,
"nome": "Maria Oliveira",
"cpf": "98765432100"
}
}
CPF deve ter 11 dígitos válidos. Senha mín. 6 caracteres. Retorna token direto.
GET
/auth/paciente/me
Dados do paciente logado
Auth Paciente
Response 200
{
"id": 1,
"nomecompleto": "José da Silva",
"cpf": "12345678901",
"telefone": "(11) 91234-5678",
"email": "jose@email.com",
"tipo": "Comum",
"telefone_validado": 1
}
POST
/auth/paciente/logout
Encerrar sessão do paciente
Auth Paciente
Response 200
{ "message": "Logout realizado com sucesso" }
Agendamentos 7 endpoints
GET
/agendamentos
Listar agendamentos (admin)
Auth Admin
Query Parameters
| Param | Tipo | Descrição |
|---|---|---|
| slotId | integer | Filtrar por slot |
| pacienteId | integer | Filtrar por paciente |
| status | string | Ativo, Cancelado, Confirmado, Não Compareceu |
GET
/agendamentos/por-data/{data}
Agendamentos por data (YYYY-MM-DD)
Auth Admin
Response 200
[{
"ca_agendamentoid": 1,
"ca_protocolo": "CA-ABC123XYZ",
"ca_status": "Ativo",
"ca_ordem": 1,
"paciente_nome": "José da Silva",
"paciente_cpf": "12345678901",
"medico_nome": "Dr. João Silva",
"especialidade_nome": "Cardiologia",
"unidade_nome": "UBS Centro",
"slot_datainicio": "2026-02-15 08:00",
"slot_datafim": "2026-02-15 09:00"
}]
GET
/agendamentos/meus
Meus agendamentos (paciente logado)
Auth Paciente
Rota exclusiva do paciente. Retorna agendamentos do paciente logado com detalhes de slot, médico, especialidade e unidade.
GET
/agendamentos/buscar-paciente
Buscar agendamentos por nome/CPF do paciente
Auth Admin
Query Parameters
| Param | Tipo | Descrição |
|---|---|---|
| q | string | Termo de busca (nome ou CPF) |
POST
/agendamentos
Criar agendamento
Auth
Request Body
{
"slotAgendaId": 123,
"pacienteId": 456
}
Response 201
{
"ca_agendamentoid": 789,
"ca_protocolo": "CA-XYZ789ABC",
"ca_ordem": 1,
"ca_status": "Ativo"
}
Gera protocolo automático (CA-XXXXXXXXX). Valida vagas disponíveis no slot.
DELETE
/agendamentos/{id}
Cancelar agendamento
Auth
Response 200
{ "message": "Agendamento cancelado com sucesso" }
Status muda para "Cancelado". Libera vaga no slot.
PUT
/agendamentos/{id}/confirmar-presenca
Confirmar presença do paciente
Auth Admin
Response 200
{ "message": "Presença confirmada" }
PUT
/agendamentos/{id}/nao-compareceu
Marcar não comparecimento
Auth Admin
Response 200
{ "message": "Não comparecimento registrado" }
Backlog / Fila de Espera 11 endpoints
GET
/backlog
Listar backlog (paginado, RBAC)
Compartilhada
Query Parameters
| Param | Tipo | Descrição |
|---|---|---|
| page | integer | Página (default: 1) |
| limit | integer | Itens por página (default: 50) |
| prioridade | string | Alta, Média, Baixa |
| especialidadeId | integer | Filtrar por especialidade |
| unidadeId | integer | Filtrar por unidade |
| medicoId | integer | Filtrar por médico |
| status | string | Pendente, Aguardando Confirmação, Agendado, Cancelado |
| search | string | Busca por nome/CPF |
Regra D-30: Itens finalizados (Agendado, Compareceu, Não Compareceu, Cancelado) com data passada são exibidos apenas dos últimos 30 dias. Paciente: vê apenas seus próprios itens.
Response 200
{
"data": [{
"backlogid": 1,
"paciente_nome": "José da Silva",
"paciente_cpf": "12345678901",
"especialidade_nome": "Cardiologia",
"prioridade": "Alta",
"status": "Pendente",
"data_preferida": "2026-02-15",
"periodo_preferido": "Manhã",
"origem": "Portal Paciente",
"tipos_slot_elegiveis": "Normal,Prioritário",
"datacriacao": "2026-02-01T10:00:00Z"
}],
"pagination": { "page": 1, "limit": 50, "total": 125, "totalPages": 3 }
}
GET
/backlog/{id}
Detalhes da solicitação (RBAC)
Compartilhada
Admin vê qualquer item. Paciente vê apenas seus próprios.
POST
/backlog
Criar solicitação no backlog
Compartilhada
Request Body
{
"pacienteId": 1,
"especialidadeId": 3,
"medicoId": null,
"unidadeId": null,
"data_preferida": "2026-02-20",
"periodo_preferido": "Manhã",
"horario_preferido": null,
"prioridade": "Alta",
"observacoes": "Urgente",
"origem": "Portal Paciente"
}
Paciente envia sem pacienteId (usa o do token). Admin envia com pacienteId. tipos_slot_elegiveis é preenchido automaticamente do cadastro do paciente.
PUT
/backlog/{id}
Atualizar solicitação
Auth Admin
Permite alterar preferências, prioridade, observações.
PATCH
/backlog/{id}/alocar
Alocar paciente em slot (operador)
Auth Admin
Request Body
{
"slotAgendaId": 42
}
Status muda para "Aguardando Confirmação". Notificação WhatsApp enviada ao paciente. Valida 3 pilares: vaga disponível, elegibilidade do tipo de slot, e cota da especialidade.
PATCH
/backlog/{id}/confirmar
Paciente confirma proposta
Compartilhada
Cria agendamento automaticamente (INSERT em ca_agendamento). Status → "Agendado". Notificação WhatsApp de confirmação.
PATCH
/backlog/{id}/recusar
Paciente recusa proposta
Compartilhada
Status volta para "Pendente". Slot é liberado. Paciente permanece na fila.
POST
/backlog/{id}/alocar-dia
Alocar paciente por dia (escolhe data)
Auth Admin
Request Body
{
"data": "2026-02-20",
"slotAgendaId": 55
}
POST
/backlog/{id}/alocar-inteligente
Alocação automática inteligente
Auth Admin
Auto-busca o melhor slot disponível com base nas preferências do paciente (data, período, especialidade, médico, unidade, tipos de slot elegíveis). Usa validação de 3 pilares.
PATCH
/backlog/{id}/inativar
Inativar solicitação (soft delete)
Auth Admin
Marca campo ativo = 0. Não aparece mais na listagem.
DELETE
/backlog/{id}
Cancelar solicitação
Auth
Response 200
{ "message": "Solicitação cancelada" }
Slots 6 endpoints
GET
/slots/disponiveis
Listar slots disponíveis (agrupados)
Compartilhada
Query Parameters
| Param | Tipo | Descrição |
|---|---|---|
| especialidadeId | integer | Filtrar por especialidade |
| medicoId | integer | Filtrar por médico |
| unidadeId | integer | Filtrar por unidade |
| dataInicio | string | Data início (YYYY-MM-DD) |
| dataFim | string | Data fim (YYYY-MM-DD) |
| tiposlotId | integer | Filtrar por tipo de slot |
Response 200
[{
"data": "2026-02-15",
"hora": "08:00",
"medicoId": 1,
"medicoNome": "Dr. João Silva",
"especialidadeId": 3,
"especialidadeNome": "Cardiologia",
"unidadeId": 2,
"unidadeNome": "UBS Centro",
"tiposlotId": 1,
"tiposlotNome": "Normal",
"limiteVagas": 10,
"agendados": 3,
"vagasDisponiveis": 7,
"disponivel": true,
"slots": [101, 102, 103]
}]
Slots são agrupados por data/hora/médico. Enriquecidos com nomes via cross-db lookup (mirrorEntity).
POST
/slots/generate-periodo
Gerar slots para um período (grade individual)
Auth Admin
Request Body
{
"gradeAgendaId": 1,
"dataInicio": "2026-02-01",
"dataFim": "2026-02-28",
"horas": ["08", "09", "10", "14", "15"],
"diasSemana": [1, 2, 3, 4, 5],
"tiposSlotDistribuicao": [
{ "tipoSlotId": 1, "quantidade": 3 },
{ "tipoSlotId": 2, "quantidade": 1 }
]
}
POST
/slots/generate-bulk
Gerar slots em massa (wizard de 5 etapas)
Auth Admin
Request Body
{
"medicoId": 1,
"unidadeId": 2,
"especialidadeId": 3,
"consultorioId": 1,
"dataInicio": "2026-02-01",
"dataFim": "2026-03-31",
"configuracaoDias": {
"1": ["08", "09", "10", "14", "15"],
"2": ["08", "09", "10"],
"3": ["14", "15", "16"],
"4": ["08", "09", "10", "14", "15"],
"5": ["08", "09", "10"]
},
"tiposSlotDistribuicao": [
{ "tipoSlotId": 1, "quantidade": 3 },
{ "tipoSlotId": 2, "quantidade": 2 },
{ "tipoSlotId": 3, "quantidade": 1 }
]
}
Response 201
{
"message": "240 slots criados com sucesso",
"resumo": {
"totalSlots": 240,
"diasProcessados": 40,
"gradeAgendaId": 5
}
}
Cria ou reutiliza grade existente (mesmo médico/unidade/especialidade). Gera slots para cada combinação dia/hora.
GET
/slots/{id}
Detalhes do slot
Auth Admin
Retorna slot com detalhes enriquecidos (nomes de médico, especialidade, unidade, tipo de slot).
PUT
/slots/{id}
Atualizar slot
Auth Admin
Permite alterar status, datas, tipo de slot, limite de vagas.
DELETE
/slots/{id}
Cancelar slot
Auth Admin
Status → "Cancelado". Cancela agendamentos vinculados.
Grade de Agenda 8 endpoints
GET
/grade-agenda
Listar grades
Auth Admin
Response 200
[{
"ca_gradeagendaid": 1,
"ca_medicoid": 1,
"ca_especialidadeid": 3,
"ca_unidadeid": 2,
"ca_consultorioid": 1,
"ca_vigencia": "Permanente",
"ca_overbooking": 0,
"ca_limitevagas": 10,
"ca_status": "Ativo",
"medico_nome": "Dr. João Silva",
"especialidade_nome": "Cardiologia",
"unidade_nome": "UBS Centro",
"consultorio_nome": "Consultório 1"
}]
GET
/grade-agenda/{id}
Detalhes da grade
Auth Admin
POST
/grade-agenda
Criar grade
Auth Admin
Request Body
{
"medicoId": 1,
"especialidadeId": 3,
"unidadeId": 2,
"consultorioId": 1,
"vigencia": "Permanente",
"overbooking": false,
"limitevagas": 10,
"status": "Ativo"
}
GET
/grade-agenda/{id}/cancelled-days
Listar dias cancelados da grade
Auth Admin
Response 200
[{
"id": 1,
"gradeagendaid": 5,
"data": "2026-02-15",
"motivo": "Feriado municipal",
"cancelado_por": "Admin",
"cancelado_em": "2026-02-10T14:00:00Z",
"restaurado": 0
}]
GET
/grade-agenda/{id}/cancelled-days/range
Dias cancelados por período
Auth Admin
Query: ?dataInicio=2026-02-01&dataFim=2026-02-28
POST
/grade-agenda/{id}/cancel-day
Cancelar dia específico
Auth Admin
Request Body
{
"data": "2026-02-15",
"motivo": "Feriado municipal"
}
Cancela automaticamente slots livres do dia. Motivo obrigatório.
PUT
/grade-agenda/{id}/restore-day
Restaurar dia cancelado
Auth Admin
Request Body
{ "data": "2026-02-15" }
Marca dia como restaurado e reativa slots que foram cancelados.
GET
/grade-agenda/{id}/day-history/{data}
Histórico de um dia específico
Auth Admin
Retorna histórico de cancelamentos e restaurações do dia.
Estatísticas da Grade 4 endpoints
GET
/grade-stats/day/{date}
Estatísticas resumidas do dia
Auth Admin
Response 200
{
"data": "2026-02-15",
"totalSlots": 50,
"totalVagas": 200,
"totalAgendados": 45,
"vagasDisponiveis": 155,
"especialidades": 5,
"medicos": 8
}
GET
/grade-stats/day/{date}/detail
Detalhes completos do dia
Auth Admin
Retorna slots, agendamentos, médicos e especialidades do dia com detalhes completos.
GET
/grade-stats/day/{date}/doctors
Médicos com agenda no dia
Auth Admin
Lista médicos que possuem slots no dia, com contagem de vagas e agendamentos.
POST
/grade-stats/check-availability
Verificar disponibilidade (3 pilares)
Auth Admin
Request Body
{
"slotAgendaId": 42,
"pacienteId": 10,
"especialidadeId": 3
}
Response 200
{
"disponivel": true,
"validacoes": {
"vagaDisponivel": true,
"tipoSlotElegivel": true,
"cotaEspecialidade": true
}
}
3 Pilares: 1) Vaga disponível no slot, 2) Tipo de slot elegível para o paciente, 3) Cota da especialidade para o tipo de slot.
Especialidades 6 endpoints
GET
/especialidades
Listar especialidades
Compartilhada
Query: ?ativas=true para filtrar apenas ativas
Response 200
[{
"ca_especialidadeid": 1,
"ca_nome": "Cardiologia",
"ca_limitevagas": 10,
"ca_status": "Ativo"
}]
POST
/especialidades
Criar especialidade
Auth Admin
{
"nome": "Dermatologia",
"limiteVagas": 8,
"status": "Ativo"
}
PUT
/especialidades/{id}
Atualizar especialidade
Auth Admin
DELETE
/especialidades/{id}
Inativar especialidade (soft delete)
Auth Admin
GET
/especialidades/{id}/cotas
Listar cotas de vagas por tipo de slot
Auth Admin
Response 200
[{
"especialidadeid": 1,
"tiposlotid": 1,
"tiposlot_nome": "Normal",
"vagas": 3
},
{
"especialidadeid": 1,
"tiposlotid": 2,
"tiposlot_nome": "Prioritário",
"vagas": 2
}]
Soma das cotas deve ser igual ao limiteVagas da especialidade.
POST
/especialidades/{id}/cotas
Definir cotas de vagas
Auth Admin
Request Body
{
"cotas": [
{ "tiposlotid": 1, "vagas": 3 },
{ "tiposlotid": 2, "vagas": 2 },
{ "tiposlotid": 3, "vagas": 1 }
]
}
Substitui todas as cotas existentes (delete + insert).
Médicos 4 endpoints
GET
/medicos
Listar médicos (enriquecido com especialidades)
Compartilhada
Query: ?especialidadeId=3 & status=Ativo
Response 200
[{
"ca_medicoid": 1,
"ca_nomecompleto": "Dr. João Silva",
"ca_crm": "123456",
"ca_crm_uf": "SP",
"ca_cpf": "12345678901",
"ca_telefone": "(11) 98765-4321",
"ca_unidadeid": 2,
"ca_limitevagas": 15,
"ca_foto_url": "https://r2.../foto.jpg",
"ca_status": "Ativo",
"especialidades": [
{ "especialidadeid": 3, "nome": "Cardiologia" },
{ "especialidadeid": 7, "nome": "Clínica Geral" }
]
}]
Especialidades via JOIN em ca_medico_especialidade.
POST
/medicos
Criar médico
Auth Admin
{
"nomeCompleto": "Dra. Maria Santos",
"crm": "654321",
"crm_uf": "SP",
"cpf": "98765432100",
"dataNascimento": "1980-03-10",
"telefone": "(11) 91234-5678",
"email": "maria@email.com",
"unidadeId": 2,
"especialidadeIds": [3, 7],
"limiteVagas": 15
}
Insere na ca_medico + ca_medico_especialidade (N:N).
PUT
/medicos/{id}
Atualizar médico
Auth Admin
Atualiza dados + recria associações de especialidades se enviadas.
DELETE
/medicos/{id}
Inativar médico (soft delete)
Auth Admin
Unidades de Saúde 5 endpoints
GET
/unidades
Listar unidades (com consultórios inline)
Compartilhada
Response 200
[{
"ca_unidadeid": 2,
"ca_nome": "UBS Centro",
"ca_tipo": "Clínica",
"ca_logradouro": "Rua Principal",
"ca_numero": "100",
"ca_bairro": "Centro",
"ca_cidade": "Barueri",
"ca_uf": "SP",
"ca_cep": "06400-000",
"ca_telefone": "(11) 4199-0000",
"ca_horario_abertura": "07:00",
"ca_horario_fechamento": "18:00",
"ca_dias_funcionamento": "1,2,3,4,5",
"ca_status": "Ativo",
"consultorios": [
{ "ca_consultorioid": 1, "ca_nome": "Consultório 1", "ca_status": "Ativo" },
{ "ca_consultorioid": 2, "ca_nome": "Consultório 2", "ca_status": "Ativo" }
]
}]
POST
/unidades
Criar unidade (com consultórios e horários)
Auth Admin
{
"nome": "UBS Jardim Paulista",
"tipo": "Clínica",
"logradouro": "Av. Brasil",
"numero": "500",
"complemento": "Bloco A",
"bairro": "Jardim Paulista",
"cidade": "Barueri",
"uf": "SP",
"cep": "06400-000",
"telefone": "(11) 4199-1111",
"horarioAbertura": "07:00",
"horarioFechamento": "18:00",
"diasFuncionamento": "1,2,3,4,5",
"horariosPorDia": {
"1": { "abertura": "07:00", "fechamento": "18:00" },
"6": { "abertura": "08:00", "fechamento": "12:00" }
},
"consultorios": [
{ "nome": "Consultório 1" },
{ "nome": "Consultório 2" }
]
}
PUT
/unidades/{id}
Atualizar unidade
Auth Admin
DELETE
/unidades/{id}
Inativar unidade (soft delete)
Auth Admin
Verifica se há grades ativas antes de inativar.
PATCH
/unidades/{id}/reativar
Reativar unidade
Auth Admin
Consultórios 5 endpoints
GET
/consultorios
Listar consultórios
Auth Admin
Query: ?unidadeId=2 & status=Ativo
POST
/consultorios
Criar consultório
Auth Admin
{
"nome": "Consultório 3",
"unidadeId": 2
}
PUT
/consultorios/{id}
Atualizar consultório
Auth Admin
DELETE
/consultorios/{id}
Inativar consultório (soft delete)
Auth Admin
Verifica se há grades ativas vinculadas.
PATCH
/consultorios/{id}/reativar
Reativar consultório
Auth Admin
Tipos de Slot 4 endpoints
GET
/tipos-slot
Listar tipos de slot
Auth
Response 200
[{
"ca_tiposlotid": 1,
"ca_nome": "Normal",
"ca_finalidade": "Consulta regular",
"ca_canalorigem": "Aberto",
"ca_cor": "#3b82f6",
"ca_agendavel": 1,
"ca_status": "Ativo"
}]
POST
/tipos-slot
Criar tipo de slot
Auth Admin
{
"nome": "Prioritário",
"finalidade": "Atendimento prioritário",
"canalOrigem": "Aberto",
"cor": "#ef4444",
"agendavel": true
}
PUT
/tipos-slot/{id}
Atualizar tipo de slot
Auth Admin
DELETE
/tipos-slot/{id}
Inativar tipo de slot
Auth Admin
Pacientes 11 endpoints
GET
/pacientes
Listar pacientes (busca por CPF/nome)
Auth Admin
Query: ?cpf=123&search=silva&limit=50
Response 200
[{
"ca_pacienteid": 1,
"ca_nomecompleto": "José da Silva",
"ca_cpf": "12345678901",
"ca_datanascimento": "1985-06-20",
"ca_telefone": "(11) 91234-5678",
"ca_email": "jose@email.com",
"ca_tipo": "Comum",
"ca_tipo_vinculo": "Munícipe",
"ca_status": "Ativo",
"ca_telefone_validado": 1,
"ca_funcionario": 0,
"ca_origem": "Portal Paciente"
}]
GET
/pacientes/{id}
Detalhes do paciente
Auth Admin
POST
/pacientes
Criar paciente (admin)
Auth Admin
{
"nomeCompleto": "Maria Santos",
"cpf": "98765432100",
"dataNascimento": "1990-05-15",
"telefone": "(11) 98765-4321",
"email": "maria@email.com",
"tipo": "Prioritário",
"tipo_vinculo": "Munícipe",
"nome_mae": "Ana Santos"
}
Detecção automática de funcionário via CPF. Status = Ativo.
PUT
/pacientes/{id}
Atualizar paciente
Auth Admin
DELETE
/pacientes/{id}
Inativar paciente (soft delete)
Auth Admin
PATCH
/pacientes/{id}/reativar
Reativar paciente
Auth Admin
POST
/pacientes/{id}/validar-telefone
Enviar código OTP via WhatsApp
Auth
Gera código de 6 dígitos. Validade: 5 minutos. Máx 3 tentativas. Cooldown 60s entre envios.
POST
/pacientes/{id}/confirmar-telefone
Confirmar código OTP
Auth
Request Body
{ "codigo": "123456" }
Se válido, marca telefone_validado = 1. Se inválido, incrementa tentativas.
DELETE
/pacientes/{id}/validacao-telefone
Remover validação de telefone
Auth Admin
Reseta telefone_validado para 0.
GET
/pacientes/{id}/tipos-slot
Tipos de slot elegíveis do paciente
Auth Admin
Response 200
[
{ "tiposlotid": 1, "nome": "Normal" },
{ "tiposlotid": 2, "nome": "Prioritário" }
]
PUT
/pacientes/{id}/tipos-slot
Atualizar tipos de slot elegíveis
Auth Admin
Request Body
{
"tipoSlotIds": [1, 2, 3]
}
Substitui todas as associações (delete + insert em ca_paciente_tiposlot).
Usuários Administrativos 4 endpoints
Requer permissão manage_users (apenas administrador_master).
GET
/usuarios
Listar usuários (paginado)
RBAC: admin_master
Query: ?page=1&limit=20&search=admin&role=operador&status=ativo
GET
/usuarios/{id}
Detalhes do usuário
RBAC: admin_master
POST
/usuarios
Criar usuário (gera senha temp + e-mail)
RBAC: admin_master
Request Body
{
"nome": "Operador Novo",
"email": "operador@barueri.sp.gov.br",
"cpf": "11122233344",
"cargo": "Operador de Agendamento",
"role": "operador"
}
Gera senha temporária aleatória + token de primeiro acesso. E-mail enviado via Mailjet.
Response 201
{
"usuario": {
"id": 5,
"nome": "Operador Novo",
"email": "operador@barueri.sp.gov.br",
"role": "operador",
"primeiro_acesso": 1
}
}
PUT
/usuarios/{id}
Atualizar usuário
RBAC: admin_master
Permite alterar nome, email, cpf, cargo, role, ativo, senha.
Upload (R2 Storage) 2 endpoints
POST
/upload/medico/{id}/foto
Upload foto do médico
Auth Admin
Content-Type: multipart/form-data
| Campo | Tipo | Descrição |
|---|---|---|
| foto | File | Imagem (JPEG, PNG, WebP). Máx 5MB |
Response 200
{
"foto_url": "https://pub-xxxxx.r2.dev/medicos/1/foto-1234567890.jpg"
}
Armazena no Cloudflare R2. Atualiza ca_medico.ca_foto_url. Deleta foto anterior se existir.
DELETE
/upload/medico/{id}/foto
Remover foto do médico
Auth Admin
Remove do R2 e limpa ca_foto_url.