🚀 Implantação pela API, na ordem correta
Roteiro passo a passo para implantar ou migrar uma clínica pela API externa — da empresa à conferência pelo Farol — com as rotas, os campos obrigatórios e os ids que cada passo entrega ao seguinte.
✅ Novo — set/2026 Ordem oficial revisada em 24/09/2026 ✅ Novo — 26/09/2026: conferência por serviço (farol/itens/{servicoRaizId}) e GET completo para o PUT ✅ Novo — 29/09/2026: contrato de 28/09 (servicoTaxa, listas por ID ou objeto, lote no estoque), token rbt_ e conferência retroativa ✅ Novo — 30/09/2026: token rbt_ da clínica é o caminho recomendado ✅ Novo — 13/10/2026: PUT parcial, 403 com escopoFaltante, repasse geral, EAN/NCM como texto, 409 em produto/taxa em uso
A correção geral da API externa de 28/09/2026 (em produção às 17:43, Brasília) acabou com rotas que respondiam sucesso sem gravar ou gravavam errado sem avisar. Se a implantação desta clínica gravou algo antes disso, confira: pacientes em lote (/pacientes/bulk podia responder criado sem gravar — compare a planilha com GET /pacientes); lote de preços da tabela interna (/tabelas-preco/produtos/bulk gravava sem converter para centavos — confira GET /tabelas-preco/produtos?id=…); movimentações alteradas por PUT sem duplicatas (parcelas apagadas); fornecedores alterados por PUT sem ativo (reativados); UF de operadora, empresa e colaborador enviados sem UF (gravada a primeira UF); saídas e transferências de estoque sem lote (baixa em lote qualquer). Lista completa das correções: Novidades da API.
Pressupõe que você leu a visão geral (URLs, autenticação, permissões e convenções). Os exemplos usam homologação e duas variáveis de ambiente — troque pela produção só depois de ensaiar o roteiro inteiro:
export BASE="https://api.hmg.rabisistemas.dev/api/v1/integrations"
export TOKEN="rbt_SEU_TOKEN" # recomendado: token rbt_ da clínica (tipo "Implantação e manutenção")
# alternativa: a chave rbk_ emitida pelo time Rabi (mesmo uso)
Confira que o token é do mesmo ambiente da URL (produção × homologação). Guarde-o numa variável de ambiente ou cofre — nunca no próprio script versionado.
Cada passo diz: rota(s), campos obrigatórios, ids que o próximo passo precisa, um exemplo mínimo, o lote disponível e como conferir. Os detalhes completos de cada rota estão na Referência — Cadastros.
Duas regras que valem para o roteiro inteiro (convenções do Swagger de 25/09/2026): (1) PUT ✅ Novo — 13/10/2026 — desde 01–02/10/2026, em serviços, convênios, pacientes, colaboradores, grades, orçamentos, movimentações e guias, campo omitido mantém, null limpa, lista omitida mantém e lista enviada substitui ([] apaga): envie só o que muda e, ao trocar uma lista, mande a lista inteira já corrigida (parta do GET, que devolve os mesmos nomes do PUT). Nas rotas cuja descrição não declara nada (produtos, taxas, equipamentos, locais, depósitos, fornecedores, fabricantes) e em /empresas/{id}, o PUT ainda sobrescreve: GET antes e objeto completo (ver convenções de PUT); (2) confira se o token vale até o fim da implantação — o cabeçalho X-ApiKey-Expires-At da primeira resposta mostra a validade (rbk_ e rbt_); o rbt_ a própria clínica renova; a rbk_, só o time Rabi.
1. A ordem oficial
A mesma ordem vale para a implantação pela tela e pela API — a API apenas recusa com um código de erro quando a ordem é violada, em vez de a tela "não mostrar a opção na lista".
Empresa → Depósito mínimo → Locais e tipos → Operadoras/Fornecedores → Taxas → Produtos (catálogo)
→ Equipamentos → Serviços (subserviços ANTES dos pais) → Colaboradores → Convênios (dados, depois abas)
→ Conferência pelo Farol → Financeiro/Estoque → Pacientes → Parâmetros e Permissões
1.1 As 3 dependências que estavam invertidas no manual
Verificadas na API e na tela em 24/09/2026. Se você seguia a ordem antiga, é aqui que a implantação travava:
| # | O manual dizia | Dependência real | Ordem correta | O erro que aparece se violar |
|---|---|---|---|---|
| 1 | Local na etapa 1; depósito só no estoque (etapa 8) | POST /locais exige depositoPadraoSaidaId de um depósito ativo (a tela também pede). E POST /produtos exige depositoId. | Criar um depósito mínimo por unidade logo após a empresa, antes dos locais. O resto do estoque continua depois. | 422 — "O depósito padrão de saída selecionado está inativo ou não existe". |
| 2 | Serviços antes do catálogo de produtos | Serviço de medicamento/material exige o produto já cadastrado: a composição (produtoIds) aponta para o produto. | Catálogo de produtos antes dos serviços. Entradas de estoque e custo podem ficar para depois. | A composição não tem para onde apontar (o id do produto ainda não existe). Consertar depois exige PUT /servicos/{id} com a lista produtoIds completa (lista enviada substitui; desde 01–02/10 o resto do serviço é preservado). |
| 3 | Taxa na etapa 7 | As abas Taxas e Serviços do convênio e a tabela de preço interna exigem as taxas cadastradas (o serviço também aponta as suas taxas em servicoTaxa). | Taxas antes dos convênios e das tabelas de preço internas. | Em PUT /convenios/{id}/taxas o item volta como ERRO dentro de um 207 (taxa inexistente). |
Um aviso interno de 25/09 dizia que a API "não cria depósito". O Swagger oficial publicado — fonte primária — tem POST /depositos e POST /depositos/bulk (empresaId* e descricaoDeposito*; 409 se o nome repetir na unidade). Portanto: a API cria depósito. O que a API não cria são os tipos auxiliares (grupo Auxiliares, só leitura) — esses se criam pela tela e você informa os ids.
2. Passo 0 — Preparação
- Token e permissões. ✅ Novo — 30/09/2026 (a) Recomendado (decisão do Diretor em 30/09): um token
rbt_que a própria clínica gera em Configurações › Parâmetros › Integrações, tipo Implantação e manutenção (em produção desde 28/09/2026), só com as permissões do kit de implantação — a clínica também o renova e revoga, sem depender do time Rabi. (b) Alternativa: a chaverbk_emitida pelo time Rabi no portal comercial com o mesmo kit — continua valendo para quem já tem; anote a data do cabeçalhoX-ApiKey-Expires-Ate, se ela vence antes do fim previsto da implantação, peça a nova ao time Rabi antes de começar (não há renovação automática nem autoatendimento para arbk_). Nos dois casos, teste comGET /empresas(deve responder200). ✅ Novo — 13/10/2026 Se faltar permissão no meio da implantação, o403diz qual emescopoFaltante: com orbt_, use Editar permissões no mesmo token (o valor não muda; vale na chamada seguinte — #653). Validade dorbt_: 30, 90, 365 dias ou sem validade; Renovar gera valor novo e invalida o anterior. O token aparece uma única vez: guarde em local seguro e nunca o cole em documento, chamado, e-mail, manual ou conversa com IA que fique salva; token de uma clínica não acessa outra; suspeita de vazamento → revogue e gere outro (detalhes). - Leia os auxiliares (só leitura) e monte o seu "dicionário de ids":
Faltou algum tipo (ex.: um tipo de taxa ou tipo de produto próprio da clínica)? Crie pela tela do sistema e leia de novo — a API não cria auxiliares.for r in tipos-produto tipos-codigo tabelas-ans87 regimes-atendimento tipos-servico tipos-guia \ tipos-taxa unidades-medida principios-ativos sexos estados-civis conselhos-profissionais \ unidades-federativas tipos-atendimento; do curl -s "$BASE/auxiliares/$r" -H "Authorization: Bearer $TOKEN" > "aux-$r.json" done - Ids que só existem na tela. O Swagger publicado não tem rota de listagem para: especialidades (catálogo), categorias de pagamento, contas/caixas, centros de custo, motivos de movimentação de estoque, kits de documentos, modelos de XML do convênio (
xmlConsultaId/xmlSpSadtId), tipos de contrato, tipos de anexo, perfis de permissão e fontes de preço de compra. Anote esses ids pela tela antes de começar (ou peça ao implantador que os informe à IA). - Planilha de origem limpa: CNPJs/CPFs únicos, nomes sem duplicidade, vazio onde não há valor (nunca
0,01como marcador de "sem valor"). - Leituras paginadas ✅ Novo — 14/10/2026: a API externa devolve no máximo 200 itens por página (#669);
pageSizemaior é reduzido sem erro. Ao conferir o que já foi carregado, percorra todas as páginas atétotalPages— ver Listagens e paginação.
3. Passo 1 — Empresa (e unidades)
POST /empresas · permissão empresa:create · sem lote (uma chamada por empresa/unidade).
Obrigatórios: razaoSocial, nomeFantasia, cnpj (único; com ou sem máscara), endereco (UF por id ou sigla). Entrega: empresaId — usado por depósitos, locais, convênios (empresaId e unidadesIds) e colaboradores (empresas).
curl -s -X POST "$BASE/empresas" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"razaoSocial": "Clínica Rabi Sistemas LTDA",
"nomeFantasia": "Clínica Rabi Sistemas",
"cnpj": "12345678000190",
"endereco": { "Cep": "70000000", "Endereco": "SBS Quadra 2", "Numero": "1",
"Bairro": "Asa Sul", "Cidade": "Brasília", "unidadeFederativaId": "DF" }
}'
Conferir: GET /empresas (sem paginação de fato — envelope com page = 1 e a lista inteira, ativas e inativas). Para corrigir depois: PUT /empresas/{id} substitui o cadastro inteiro — envie a empresa completa. 409 = CNPJ já existe (inclusive em empresa desativada): reutilize o id existente.
4. Passo 2 — Depósito mínimo por unidade dependência corrigida
POST /depositos ou POST /depositos/bulk (até 50) · deposito:create.
Obrigatórios: empresaId, descricaoDeposito. Entrega: depositoId — exigido por POST /locais (depositoPadraoSaidaId) e por POST /produtos (depositoId).
curl -s -X POST "$BASE/depositos/bulk" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"depositos": [
{ "empresaId": 54, "descricaoDeposito": "Depósito Central" }
]
}'
Conferir: GET /depositos?ativo=true. 409 = já existe depósito com esse nome nessa unidade. Crie só o mínimo agora; depósitos adicionais, entradas e saldos ficam para o passo 12.
5. Passo 3 — Locais (e tipos) dependência corrigida
POST /locais · local:create · sem lote.
Obrigatórios: nome, empresaId, depositoPadraoSaidaId (depósito ativo). Entrega: localId — usado nas grades e na agenda.
curl -s -X POST "$BASE/locais" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"nome": "Consultório 1", "empresaId": 54, "depositoPadraoSaidaId": 3
}'
Se violar a ordem: 422 "O depósito padrão de saída selecionado está inativo ou não existe". 409 = já existe um local com esse nome nessa empresa. Tipos: é aqui que se conferem os tipos auxiliares da clínica (passo 0) — os que faltarem, crie pela tela. Conferir: GET /locais. Corrigir: PUT /locais/{id} não declara o comportamento → envie o local completo.
6. Passo 4 — Operadoras (com planos), fornecedores e fabricantes
| Cadastro | Rota (lote) | Obrigatórios | Entrega |
|---|---|---|---|
| Operadora | POST /operadoras · /operadoras/bulk (50) | nome, descricao, registroANS, cnpj, codigoCNES, endereco (cep, endereco, numero, bairro, cidade, unidadeFederativa por extenso); plano[].nome se enviar planos | operadoraId (convênio) e os ids dos planos (GET /operadoras/{id} → plano[].id), usados na aba Planos do convênio e no vínculo do paciente |
| Fornecedor | POST /fornecedores · /fornecedores/bulk (50) | nome, cnpj, inscricao, telefoneFornecedor | fornecedorId (produto, estoque, financeiro) |
| Fabricante | POST /fabricantes · /fabricantes/bulk (50) | nome | fabricanteId — obrigatório em POST /produtos |
curl -s -X POST "$BASE/operadoras/bulk" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"operadoras": [{
"nome": "Operadora Exemplo", "descricao": "Operadora Exemplo", "registroANS": "123456",
"cnpj": "11222333000181", "codigoCNES": "1234567", "identificacaoPrestadorXML": "CNPJ",
"endereco": { "cep": "70000000", "endereco": "SBS Quadra 2", "numero": "1",
"bairro": "Asa Sul", "cidade": "Brasília", "unidadeFederativa": "Distrito Federal" },
"plano": [ { "nome": "Plano Ouro" }, { "nome": "Plano Prata" } ]
}]
}'
Atenção: identificacaoPrestadorXML define como o prestador aparece no XML TISS (CNPJ ou CODIGO_NA_OPERADORA — o XSD só aceita um). Em PUT /operadoras/{id} mande as listas completas de plano e contato (o que faltar é removido). Conferir: GET /operadoras/{id}, GET /fornecedores, GET /fabricantes.
7. Passo 5 — Taxas dependência corrigida
POST /taxas · /taxas/bulk (50) · taxa:create.
Obrigatórios: taxas (o nome da taxa), codigoTaxa, tipoTaxaId (de GET /auxiliares/tipos-taxa), valor (em reais). Opcionais relevantes: tipoCodigoId, tabelaANS87ID. Entrega: taxaId — usado pela aba Taxas do convênio e pela lista servicoTaxa do serviço.
curl -s -X POST "$BASE/taxas/bulk" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"taxas": [ { "taxas": "Taxa de sala", "codigoTaxa": "TX-001", "tipoTaxaId": 1, "valor": 73.99 } ]
}'
Conferir: GET /taxas?ativo=true. Observação: POST /taxas responde 200 (não 201) ao criar. Corrigir: PUT /taxas/{id} com a taxa completa (a rota não declara que omitido mantém). Desativar (DELETE /taxas/{id}) uma taxa que está em serviço ativo responde 409 com a lista dos serviços — ver o quadro do passo 8.
8. Passo 6 — Produtos (catálogo) dependência corrigida
POST /produtos · /produtos/bulk (50) · produto:create.
Obrigatórios: nome, codigoProduto, apresentacao, contendo (quantidade na embalagem), depositoId, tipoProdutoId, fabricanteId, unidadeDeMedidaId, prazoDeReposicao (dias). Opcionais relevantes: principioAtivoId, tipoCodigoId, tabelaANS87ID, fornecedores (ids), estoquePodeNegativar, precoUltimaPesquisa/dataUltimaPesquisa, codigoEAN e codigoNCM. ✅ Novo — 13/10/2026 (#635) codigoProduto até 10 caracteres (letras, números, ponto, hífen ou barra — padrão TISS); codigoEAN como texto com 8, 12, 13 ou 14 dígitos (preserva o zero à esquerda; número ainda é aceito, mas perde os zeros); codigoNCM texto com exatamente 8 dígitos. Entrega: produtoId — composição dos serviços, aba Produtos do convênio, tabela interna, estoque.
curl -s -X POST "$BASE/produtos/bulk" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"produtos": [{
"nome": "Soro fisiológico 500ml", "codigoProduto": "PRD-500", "apresentacao": "Frasco 500ml",
"contendo": 1, "depositoId": 3, "tipoProdutoId": 1, "fabricanteId": 8,
"unidadeDeMedidaId": 2, "prazoDeReposicao": 15
}]
}'
422 = referência inválida (depósito, tipo, fabricante ou unidade inexistente). O preço de venda calculado não é exposto pela API; entradas de estoque e custo ficam para o passo 12. Conferir: GET /produtos?ativo=true&nome=soro. Corrigir: PUT /produtos/{id} com o produto completo (a rota não declara que omitido mantém). Desativar (DELETE /produtos/{id} ou PUT com ativo: false) um produto que está em serviço ativo responde 409 — ver o quadro do passo 8.
9. Passo 7 — Equipamentos
POST /equipamentos · /equipamentos/bulk (50) · só nome é obrigatório (409 se já existir equipamento ativo com o mesmo nome). Entrega: equipamentoId — composição do serviço (equipamentoIds) e grade de equipamento.
curl -s -X POST "$BASE/equipamentos/bulk" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"equipamentos": [ { "nome": "Ultrassom Sala 2" } ]
}'
10. Passo 8 — Serviços (subserviços ANTES dos pais)
POST /servicos · /servicos/bulk (50) · servico:create.
Obrigatórios: nome, descricao. Relevantes para preço e faturamento: valor (reais), somarItems, codigo, codigoTUSS, tempoServico (min), tipoServicoId, tipoCodigoId, tipoGuiaId, tabelaANS87ID, regimeDeAtendimentoId, tipoAtendimento (id), especialidadesId, ✅ Novo — 13/10/2026 documentos (documentos obrigatórios do serviço, ex.: PRESCRIÇÃO MÉDICA — [{ "id": 3 }]; exigidos no agendamento, no acolhimento, na autorização e pela IA) e perfilFiscalId (perfil fiscal da NFS-e; null desvincula). Composição (✅ contrato de 28/09/2026): produtoIds e equipamentoIds — cada item como ID puro ou objeto (120 ou { "id": 120, "quantidade": 2, "valorUnitario": 12.50 }; equipamento { "id": 5 }); servicoTaxa: [{ "taxaId": 15, "quantidade": 1 }] para as taxas do serviço (saíram taxaServicoId e valorTaxaServico — o valor da taxa vem do cadastro da taxa e da aba Taxas do convênio); servicosRelacionados — ids de subserviços já criados, como ID puro ou { "servicoId": 46, "quantidade": 1 }. Campo opcional omitido não derruba mais a rota (até 28/09, POST /servicos sem especialidadesId dava 500 … reading 'filter'). Entrega: servicoId.
- Primeiro os subserviços (serviços que entram dentro de outros — ex.: "Aplicação endovenosa"). Guarde os ids.
- Depois os serviços pais, informando os subserviços em
servicosRelacionados. Não dá para apontar um id que ainda não existe — e corrigir depois exigePUT /servicos/{id}com a listaservicosRelacionadoscompleta (lista enviada substitui; o resto do serviço é preservado desde 01–02/10/2026).
# 1) subserviço
curl -s -X POST "$BASE/servicos" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"nome": "Aplicação endovenosa", "descricao": "Aplicação endovenosa", "valor": 40,
"servicoTaxa": [ { "taxaId": 15, "quantidade": 1 } ]
}'
# 2) serviço pai que contém o subserviço (id 46) e o produto (id 120)
# (ID puro = quantidade 1; objeto = quantidade/valor próprios)
curl -s -X POST "$BASE/servicos" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"nome": "Noripurum aplicado EV", "descricao": "Noripurum aplicado EV",
"somarItems": true,
"produtoIds": [ { "id": 120, "quantidade": 1 } ],
"servicosRelacionados": [ { "servicoId": 46, "quantidade": 1 } ]
}'
somarItems decide (regra vigente desde 23–24/09)somarItems é o "Definir preço do serviço pelos itens" da tela: decide só o valor próprio do serviço (zero quando marcado). Ele não decide mais se os itens entram — taxas, produtos e subserviços com Utiliza no convênio sempre entram na conta do serviço, cada um com a sua conversão. Detalhes: regra única do serviço composto e árvore de decisão de preços.
Conferir: GET /servicos/{id} (traz a composição completa e, na leitura, o campo somarItens; na escrita o nome do campo é somarItems). A listagem GET /servicos é resumida. Para corrigir: PUT /servicos/{id} parcial ✅ Novo — 13/10/2026 — envie só o que muda: campo omitido mantém, null limpa (valor: null vira 0), lista omitida mantém, lista enviada substitui. Ex.: { "nome": "X" } só renomeia; { "documentos": [{ "id": 3 }] } deixa só o documento 3. Produto da composição enviado sem valorUnitario mantém o valor que já tinha (produto novo sem valor entra com 0).
✅ Novo — 26/09/2026 Leitura segura para o PUT: GET /servicos/{id} agora devolve especialidadesId e servicosRelacionados (a composição) com os mesmos nomes que o PUT espera. Antes, regravar um serviço a partir do GET apagava a composição e as especialidades, porque essas listas não voltavam na leitura. Receita: GET → altere só o necessário → PUT com o objeto completo — incluindo servicoTaxa, produtoIds e equipamentoIds (o Swagger garante no GET a composição por subserviços e as especialidades; confira se as demais listas vieram e, se faltar alguma, monte-a antes do PUT, senão ela não é preservada). ✅ Atualização 13/10/2026: desde 01–02/10 (#634) o PUT de serviço é parcial — lista omitida é preservada; a leitura devolve documentos, produtos, equipamentos e taxas com os nomes do PUT.
DELETE /produtos/{id}, PUT /produtos/{id} com ativo: false e DELETE /taxas/{id} — e a exclusão pela tela — respondem 409 se o item estiver na composição de algum serviço ativo; a resposta traz a lista em servicos (serviço inativo não bloqueia). Para trocar o item: (1) substitua-o nesses serviços (PUT /servicos/{id} com a lista produtoIds ou servicoTaxa completa, já com o substituto); (2) marque utiliza/zerarValor do substituto nas abas do convênio; (3) desative o antigo e confira em GET /convenios/{id}/farol/itens/{servicoRaizId}.
Histórico: até 02/10/2026 a desativação era livre e o item sumia da composição sem aviso.
11. Passo 9 — Colaboradores e login
POST /colaboradores · /colaboradores/bulk (50) · colaborador:create — só cadastra, não cria acesso.
Obrigatórios: nome, cpf, dataDeNascimento, sexoId, telefone, celular, email, endereco (UF por extenso). Se enviar especialidades[]: uf (id), numeroConselho, especialidadeId, conselhoProfissionalId (de GET /auxiliares/conselhos-profissionais). Opcionais: empresas (ids das unidades onde atua), conselho[], corNaAgenda, vinculoRepasse — ✅ Novo — 13/10/2026 em cada lista (servicos, produtos, taxas), o item com servico/produto/taxa vazio ou null é a linha de repasse geral do tipo (vale para todo item sem linha própria; no máximo uma por tipo — 400 se vierem duas); a linha específica substitui a geral; específica com 0 e 0% = sem repasse naquele item; tipo sem nenhuma linha = sem repasse (#643). O repasse entra no custo do Farol desde 12/10/2026. Entrega: colaboradorId — aba Colaboradores do convênio, grades, e responsavelId de todas as escritas operacionais.
Login de verdade: POST /colaboradores/{id}/usuario (colaborador:update) cria o acesso no sistema (e-mail + senha, mínimo 8 caracteres). 409 se o colaborador já tiver login. Se o e-mail já tem acesso ao Rabi (ex.: em outra clínica), o usuário é vinculado a esta clínica e continua com a senha que já usa — a senha enviada não é aplicada.
curl -s -X POST "$BASE/colaboradores/60/usuario" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"email": "ana.rocha@clinicarabi.exemplo", "senha": "SENHA_FORTE_AQUI"
}'
Permissões de tela do usuário (perfis) são configuradas pela tela; a API só expõe as permissões de dashboard (grupo Parâmetros). Conferir: GET /colaboradores/{id}. Corrigir: PUT /colaboradores/{id} parcial (campo omitido mantém; vinculoRepasse.servicos/produtos/taxas só são trocadas quando enviadas; não reativa colaborador desativado; sucesso responde o número cru 201).
12. Passo 9b — Tabela de preço interna (preço de produto)
Depois das taxas e dos produtos e antes dos convênios (a política de preço do convênio pode apontar para ela):
- POST
/tabelas-preco— obrigatóriosnameepriceType1(nome do "Preço 1";priceType2/priceType3opcionais). - POST
/tabelas-preco/produtos/bulk(até 200, chaveprecos) — cada item:purchasePriceSourceId(id da tabela) +productIde os valorespriceType1..3em reais (ex.:19547.56= R$ 19.547,56; omitido mantém,nulllimpa — #652). É upsert: reenviar atualiza o preço. Lotes enviados antes de 28/09/2026: confira os valores.
curl -s -X POST "$BASE/tabelas-preco/produtos/bulk" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"precos": [ { "purchasePriceSourceId": 4, "productId": 120, "priceType1": 12.00 } ]
}'
Conferir: GET /tabelas-preco (envelope padrão { dados, page, … }), GET /tabelas-preco/produtos?id=4 e GET /tabelas-preco/precificacao. Renomear a tabela: PUT /tabelas-preco/{id} com o objeto completo.
13. Passo 10 — Convênios em 2 fases
13.1 Fase 1 — dados do convênio
POST /convenios · /convenios/bulk (50) · convenio:create.
Obrigatórios: descricao, dataInicio, empresaId ("Empresa Principal"), unidadesIds (unidades onde o convênio é aceito na agenda). Relevantes: operadoraId, cnpj (único por clínica; no /bulk de convênios, cnpj também é obrigatório — schema ConvenioLoteItem, é a chave que recusa convênio já cadastrado ou repetido no lote), registroANS (na criação o código ANS vai aqui), prazos (prazoPagamento, prazoRetorno, prazoRecursoGlosa…), fatorK, xmlConsultaId/xmlSpSadtId, politicasPorTipoProduto[] (tipoProdutoId, fatorK, idJson com fontePrecoId e tipoPrecificacao) — nível 2 de preço do produto.
curl -s -X POST "$BASE/convenios" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"descricao": "Operadora Exemplo — Plano Empresarial",
"nomeFantasia": "Operadora Exemplo", "cnpj": "11222333000181", "registroANS": "123456",
"dataInicio": "2026-10-01T00:00:00.000Z",
"empresaId": "54", "unidadesIds": [54], "operadoraId": "3",
"prazoPagamento": 30, "prazoRetorno": 30
}'
409 = CNPJ já existe; 422 = empresa, operadora ou kit não encontrado. No lote, reenviar o lote inteiro é seguro (os já criados são recusados por CNPJ duplicado). PUT /convenios/{id} é parcial desde 01–02/10/2026 ✅ Novo — 13/10/2026: campo omitido mantém (inclusive empresaId, unidadesIds, operadoraId e as datas); null limpa; unidadesIds e politicasPorTipoProduto, quando enviados, são a lista completa (o que faltar é desativado/inativado). Ver convenções de PUT.
13.2 Fase 2 — as abas (PUT em lote, upsert)
Na aba Especialidades (PUT /convenios/{id}/especialidades, campo utiliza = coluna Atende da tela), marque todas as especialidades que o convênio cobre antes de configurar os serviços e os profissionais do convênio (ordem 2 da tabela abaixo). 🟡 Parcial Desde 02/10/2026 ela vale no cadastro do convênio: o upsert de serviços e de colaboradores do convênio (PUT /convenios/{id}/servicos, /colaboradores) recusa marcar Utiliza em serviço de especialidade não atendida — por isso as especialidades vêm primeiro. No agendamento e no orçamento a trava está desligada desde 06/10/2026 (temporário). A consulta de disponibilidade da IA (TalkMe, #633) é a exceção: ela respeita a coluna Atende — por isso a IA pode dizer que não há horário num caso que a recepção consegue agendar. Convênio sem nenhuma especialidade marcada como Atende não restringe nada; serviço sem especialidade não passa pela trava.
✅ Em produção desde 09/10/2026 — #633 A consulta única de disponibilidade da IA de atendimento (TalkMe) usa este cadastro (e o painel Disponibilidade por Convênio da Agenda, via catálogo #659, também): utiliza nos serviços e Atende nas especialidades do convênio, serviços e convênios na grade do profissional (passo 10b), Atende convênio no cadastro do profissional e o convênio ativo nas unidades onde é atendido (unidadesIds). Faltando algo, a IA dirá que não há atendimento, mesmo que a recepção consiga agendar pela tela.
✅ Novo — 30/09/2026 A API não tem "modo consulta": desde 29/09 (#632) as telas de convênio só gravam depois de Liberar para edição e, desde 01/10, do Salvar; pela API, estas rotas gravam direto, como sempre (o autor aparece como API externa no Histórico do convênio). Todas com convenio:update, uma por vez por convênio (a segunda simultânea recebe 429). Campo omitido mantém; null nos valores limpa (volta a "vazio" → o valor desce para o nível de baixo); 0 é zero de verdade.
| Ordem | Aba | Rota | Chave do item | Máx. | Campos que mais importam |
|---|---|---|---|---|---|
| 1 | Planos | PUT /convenios/{id}/planos | planoId | 200 | utiliza (coluna Atende) |
| 2 | Especialidades | PUT /convenios/{id}/especialidades | especialidadeId | 200 | utiliza (Atende), dataInicio, dataFim |
| 3 | Taxas | PUT /convenios/{id}/taxas | taxaId | 200 | utiliza, zerarValor, valorConvertido, nomeConvertido, descricaoConvertida, codigo, tipoCodigoId, tabela87ANSId |
| 4 | Produtos | PUT /convenios/{id}/produtos | produtoId | 200 | utiliza, zerarValor, valorUnitarioConversao, fatorK, fontePrecoCompraOptionsId, tipoPrecificacao (PRECO_1..3), códigos TUSS/TISS, tabela87ANSId |
| 5 | Serviços | PUT /convenios/{id}/servicos | servicoId | 200 | utiliza, pacote, zerarValor, valorInternoConvenio, tipoAtendimentoId, autorizacaoPrevia, retornoServico, codigoTuss/codigoConvenio, tabela87ANSId |
| 6 | Colaboradores | PUT /convenios/{id}/colaboradores | colaboradorId | 100 | credenciado, atende (só true se credenciado ou com conversão), colaboradorConvertidoId, especialidadesIds (aditivo) |
curl -s -X PUT "$BASE/convenios/12/taxas" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"taxas": [ { "taxaId": 15, "utiliza": true, "valorConvertido": 73.99 } ]
}'
curl -s -X PUT "$BASE/convenios/12/produtos" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"produtos": [ { "produtoId": 120, "utiliza": true, "valorUnitarioConversao": null, "fatorK": "20" } ]
}'
curl -s -X PUT "$BASE/convenios/12/servicos" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"servicos": [
{ "servicoId": 46, "utiliza": true },
{ "servicoId": 47, "utiliza": true, "pacote": true, "valorInternoConvenio": 350.00 }
]
}'
valorInternoConvenio sozinho NÃO fecha pacote (regra vigente)O valor combinado do serviço (servicos[].valorInternoConvenio) muda só o preço do próprio serviço: sem pacote: true, taxas, produtos e subserviços com utiliza continuam somando por cima e o zerarValor deles nem é consultado. Pacote é sempre marcação por convênio (não existe no cadastro do serviço). Para um preço fechado que já inclui itens, envie as três coisas:
# 1) serviço: valor combinado + pacote
curl -s -X PUT "$BASE/convenios/12/servicos" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"servicos": [ { "servicoId": 47, "utiliza": true, "valorInternoConvenio": 350.00, "pacote": true },
{ "servicoId": 46, "utiliza": true, "zerarValor": true } ]
}'
# 2) itens inclusos: zerarValor nas abas produtos/taxas (item cobrado à parte: zerarValor false)
curl -s -X PUT "$BASE/convenios/12/produtos" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"produtos": [ { "produtoId": 120, "utiliza": true, "zerarValor": true } ]
}'
curl -s -X PUT "$BASE/convenios/12/taxas" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"taxas": [ { "taxaId": 15, "utiliza": true, "zerarValor": true } ]
}'
Em PUT /convenios/{id}/servicos: valorInternoConvenio: null limpa o valor combinado (volta a vazio); campo omitido mantém. Envie zerarValor explicitamente em cada item (não dependa de valor padrão — desde 25/09/2026, criar o vínculo marcando só pacote não liga mais o Zerar). Confira depois em GET /convenios/12/farol/itens/47: os itens inclusos devem vir com conta_no_total: false e motivo_exclusao: "ZERADO_EM_PACOTE"; os cobrados à parte, com conta_no_total: true.
✅ em produção desde 24/09 A coluna Valor do serviço no convênio tem 4 linhas na tela (cadastro, combinado, valor próprio que vai na guia e Σ total). somarItens aparece no Swagger (cadastro do serviço — GET /servicos/{id}); efetivo.totalConvenio (o Σ = total do serviço no convênio = receita do Farol) existe na API do sistema (usada pela tela) — na API externa não aparece no Swagger. Pela API externa, leia o total em receita_total_servico (linha nivel = 0) de GET /convenios/{id}/farol/itens/{servicoRaizId}, ou em /farol/servicos (receita_total).
- Zero é zero, vazio é vazio. Vazio (
null/nunca preenchido) desce para o nível de baixo (política do convênio → catálogo);0é zero. Nunca use0.01como "sem valor". - Utiliza = o convênio cobre o item. Sem Utiliza: custo sem receita (fora da receita do Farol; no orçamento entra a R$ 0). Com Utiliza: cadeia de conversão do convênio — nunca o preço da casa.
- Itens sempre entram na conta do serviço (taxas, produtos, subserviços com Utiliza), cada um com a sua conversão. Só ficam fora: sem Utiliza, ou zerado em pacote de preço fechado (
pacote: true+ valor fixo ou combinado, inclusive 0). - Zerar é por item e não desce em cascata. Subserviço zerado perde só o próprio valor; os itens dentro dele seguem o próprio Zerar. Só a falta de Utiliza no subserviço tira tudo o que está dentro dele.
- Preço fixo ou valor combinado que deve "já incluir" itens →
pacote: trueno serviço +zerarValor: truenos itens inclusos.valorInternoConveniosozinho não é pacote.
Tabela-verdade e exemplos: Guia do Implantador de preços · Árvore de decisão.
Resposta: 200 = tudo processado; 207 = confira resultados[] (indice, status CRIADO/ATUALIZADO/ERRO/NAO_PROCESSADO, erro). Reenviar tudo é seguro (idempotente). Conferir cada aba: GET /convenios/{id}/taxas, /produtos, /servicos, /especialidades, /planos, /colaboradores.
14. Passo 10b — Grades de horário
Depois de colaboradores, equipamentos, locais e convênios (a grade lista os convênios atendidos). Informe na grade os serviços (servicos[]) e os convênios (convenio[]) — a consulta de disponibilidade da IA TalkMe (#633, em produção desde 09/10/2026) depende deles:
- POST
/grades-colaborador— corpo{ "colaboradorGrade": [ … ] }, vários horários de uma vez. Obrigatórios por item:colaboradorId,inicioAtendimento,fimAtendimento,tempoAtendimento(min),repetir(ex.:SEMANALMENTE),diasDaSemana(ex.:SEG,TER,QUA). Opcionais:localId,convenio[](id,limite),especialidades[],servicos[],equipamento[], encaixes,agendamentoOnline, vigência. 409 = conflito com grade existente. - POST
/grades-equipamento— o corpo é a lista direta (sem envelope). Obrigatórios:localId,equipamentoId,diaDaSemana,inicioAtendimento,fimAtendimento,gradeEmMinutos. Conflito → 422.
curl -s -X POST "$BASE/grades-colaborador" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"colaboradorGrade": [{
"colaboradorId": 60, "localId": 7,
"inicioAtendimento": "2026-10-01T08:00:00.000Z", "fimAtendimento": "2026-10-01T12:00:00.000Z",
"tempoAtendimento": 30, "repetir": "SEMANALMENTE", "diasDaSemana": "SEG,QUA,SEX",
"convenio": [ { "id": 12 } ]
}]
}'
Conferir: GET /grades-colaborador?colaboradorId=60&localId=7&vigenteEm=2026-10-01 (ou GET /grades-colaborador/filter?colaboradorId=60&localId=7) e GET /grades-equipamento?equipamentoId=…&localId=…&vigenteEm=…. As duas listagens são paginadas de verdade (page/pageSize, envelope padrão) e aceitam os filtros colaboradorId/equipamentoId, localId e vigenteEm (só grades vigentes na data) — use-os para não trazer a grade inteira da clínica. Corrigir um horário: PUT /grades-colaborador/{id} / PUT /grades-equipamento/{id} — parcial desde 01–02/10/2026 (listas convenios/servicos enviadas substituem; trocar modoConvenio inverte o sentido da lista de convênios).
15. Passo 11 — Conferência pelo Farol
A conferência final de cada convênio é o Farol — a mesma leitura da tela Configurações › Convênios › aba Farol e do painel Expandir serviço (mesma fonte no banco):
| Rota | O que mostra | Filtros úteis |
|---|---|---|
GET /convenios/{id}/farol/itens/{servicoRaizId} ✅ Novo — 26/09/2026 | Árvore de UM serviço (= Expandir serviço), sem paginação ({ dados: [...] }, poucas dezenas de linhas), com farol_servico, margem_servico_pct e totais por subárvore. Preferível quando você já sabe o serviço. 404 = serviço não utilizado neste convênio | — (o serviço vai no caminho) |
GET /convenios/{id}/farol/itens | Árvore de composição (aba Farol › Itens): uma linha por item de cada serviço — produtos, taxas e subserviços (paginada) | servicoRaizId, itemTipo, itemNome, search, apenasAtivosNoConvenio, servicoAtivo |
GET /convenios/{id}/farol/servicos | Uma linha por serviço com o total: custo_total, receita_total, receita_propria_servico, margem_resultado_pct, farol | farol (lista separada por vírgula), ativoNoConvenio, servicoAtivo, sortBy/sortOrder |
GET /convenios/{id}/farol/produtos | Uma linha por produto: custo, receita, margem_resultado_pct, farol | farol, ativoNoConvenio, produtoAtivo |
# um serviço (preferível): árvore inteira, sem paginação
curl -s "$BASE/convenios/12/farol/itens/47" -H "Authorization: Bearer $TOKEN"
# vários serviços: árvore paginada
curl -s "$BASE/convenios/12/farol/itens?apenasAtivosNoConvenio=true&servicoAtivo=true&pageSize=200" \
-H "Authorization: Bearer $TOKEN"
# linha de exemplo (campos do Swagger de 26/09/2026; valores em reais, ilustrativos):
# { "servico_raiz_id": 47, "servico_raiz": "Noripurum aplicado EV", "convenio_id": 12,
# "item_tipo": "PRODUTO", "nivel": 1, "servico_pai_id": 47, "item_id": 120,
# "item_nome": "Soro fisiológico 500ml", "codigo": "PRD-500", "tabela_ans_87": "19",
# "zerar_valor": true, "conta_no_total": false,
# "motivo_exclusao": "ZERADO_EM_PACOTE", "quantidade": 1, "quantidade_efetiva": 1,
# "custo_unitario": 8.5, "receita_unitaria": 12, "custo_item_total": 8.5, "receita_item_total": 0,
# "custo_total_servico": …, "receita_total_servico": …, "margem_servico_pct": …,
# "farol_servico": "VERDE", "utiliza_no_convenio": true, "pacote_pai": true }
# receita_item_total = 0 porque o item está zerado no pacote (cada linha reflete só ela).
# Os totais/margem/farol "_servico" são do serviço (ou da subárvore, na linha de SUBSERVICO):
# leia-os na linha nivel = 0 para o serviço inteiro.
Filtros de ativo: apenasAtivosNoConvenio=true traz só itens ativos no convênio; servicoAtivo=true traz só árvores cujo serviço raiz está ativo no cadastro (o mesmo filtro que já existe em /farol/servicos). Para o relatório de conferência, combine os dois: …/farol/itens?apenasAtivosNoConvenio=true&servicoAtivo=true.
15.1 Como ler cada linha de farol/itens
- Cada linha reflete só ela (regra de 24/09/2026): o valor efetivamente considerado — zero quando o item está fora da conta —, o custo, a receita, a margem e o farol da própria linha. A linha do serviço traz o total do serviço; a linha de um subserviço traz o total do que está dentro dele.
- ✅ Correção 26/09/2026 Pela API, cada linha traz (em reais):
servico_raiz_id,servico_raiz,convenio_id,convenio,item_tipo(SERVICO_RAIZ/SUBSERVICO/PRODUTO/TAXA),nivel(0 = raiz),caminho,servico_pai_id,servico_pai,item_id,item_nome,item_descricao,codigo,tipo_codigo,tabela_ans_87,zerar_valor,somar_itens,conta_no_total,motivo_exclusao,unidade_medida,quantidade,quantidade_efetiva,custo_unitario,receita_unitaria,custo_item_total,receita_item_total,custo_total_servico,receita_total_servico,margem_servico_pct,farol_servico(VERDE/AMARELO/VERMELHO/SEM_CUSTO),utiliza_no_convenio,pacote_pai. Ou seja: a API traz a margem, o "Conta no total" e o motivo — igual à tela (até 25/09 este manual dizia o contrário). conta_no_total: false→ o item ficou fora da receita;motivo_exclusaodiz por quê:NAO_UTILIZA_NO_CONVENIO(sem Utiliza),ZERADO_EM_PACOTE(Zerar dentro de pacote de preço fechado) ouPAI_FORA_DO_TOTAL(dentro de subserviço sem Utiliza). Na tela, os mesmos motivos aparecem como "Convênio não utiliza", "Zerado em pacote" e "Subserviço pai fora do total".- Margem do Rabi =
receita ÷ custo × 100, comparada aos limites de Configurações › Parâmetros: verde (≥ limite amarelo), amarelo (≥ limite vermelho e < limite amarelo — exatamente no limite vermelho é amarelo desde 12/10/2026), vermelho (abaixo do limite vermelho); produto com custo 0 → roxo; custo total 0 → sem cor. ✅ Novo — 13/10/2026 Desde 12/10/2026 o custo soma também os custos extras do convênio, os prestadores e o repasse do profissional (#655 — cadastrados pela tela: aba Custos extras e painel Serviços extras do convênio; detalhes em Preços › custos extras). utiliza_no_convenio: false→ o item é custo sem receita (fica fora da receita). Se a clínica cobra esse item do convênio, volte à aba e marque Utiliza.- Item que deveria cobrar e aparece com receita
0: semotivo_exclusao = ZERADO_EM_PACOTE, ele está zerado dentro de um pacote de preço fechado; seconta_no_totalétruee a receita é 0, o valor foi gravado como0quando deveria estar vazio (null). - Item que sumiu da árvore: pode ter sido desativado antes de 02/10/2026, quando isso ainda era livre (desde então dá 409 — ver quadro do passo 8).
- Roxo em produto logo após a implantação costuma ser falta de custo: o custo vem das entradas de estoque (passo 12). Confira de novo depois delas.
Detalhes da conta: como conferir (Guia do Implantador) e árvore de decisão de preços.
16. Passo 12 — Financeiro e estoque
- Estoque:
POST /estoque/entrada(obrigatóriosresponsavelId,produtoId,localizacaoId= id do depósito,motivoIdde ENTRADA,quantidade;valorCompraem reais,lote,validade,fornecedorId). Também/estoque/saida(recusa sem saldo, salvopermitirNegativo: true) e/estoque/transferencia— nas duas,loteé obrigatório desde 28/09/2026: informe o lote de onde sai o estoque ou envie"lote": nullpara produto sem lote (antes, sem lote, o sistema baixava de um lote qualquer). Saldo:GET /estoque/saldo-produtos(envelope padrão). Entradas:GET /estoque?produtoId=…&localizacaoId=…(paginado). Depósitos adicionais:POST /depositos.valorCompraé em reais. - Financeiro:
POST /financeiro/movimentacoesou/bulk(50, mesmoresponsavelId) — obrigatóriosresponsavelId,tipoMovimentacaoFinanceira,tipoFinanceiro(PAGAMENTO/RECEBIMENTO),categoriaDePagamentoId,contasCaixaId,data,parcelas,registroFinanceiro[]. Pode disparar NFS-e automática conforme o emitente — em migração de saldo histórico, confira a configuração fiscal antes. Conferir:GET /financeiro/movimentacoes(envelope padrão). Corrigir:PUT /financeiro/movimentacoes/{id}parcial (registroFinanceiroeduplicatasomitidos não mudam; lista enviada substitui). ✅ Novo — 13/10/2026 Baixa automática de Pix/link:POST /financeiro/pagamentos/confirmacao(financeiro:update) — os Links de Pagamento (#409) ainda são roadmap.
17. Passo 13 — Pacientes
POST /pacientes/bulk (50 por requisição, um lote por vez) · paciente:create.
Obrigatórios: nome, sexoId, contato[] (cada contato com email e celular), endereco, e cpf — salvo recém-nascido sem CPF (atendimentoRn: true + cpfMae). Convênio no mesmo corpo: convenioPlano[] (convenioId*, planoId, numeroDaCarterinha, validade). ✅ Novo — 13/10/2026 Opcional: nomeSocial (exibido nas telas como "SOCIAL (civil)" e enviado no campo Nome Social da guia/XML TISS).
curl -s -X POST "$BASE/pacientes/bulk" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"pacientes": [{
"nome": "Maria Exemplo", "cpf": "CPF_VALIDO_AQUI", "sexoId": 2, "dataDeNascimento": "1980-05-10",
"contato": [ { "email": "maria@exemplo.com", "celular": "61999990000" } ],
"endereco": { "cep": "70000000", "cidade": "Brasília", "unidadeFederativaId": 7 },
"convenioPlano": [ { "convenioId": 12, "planoId": 4, "numeroDaCarterinha": "0001234" } ]
}]
}'
409 (no simples) = CPF já cadastrado nesta clínica; 400 = CPF inválido ou contato obrigatório ausente. Vínculos depois: POST /pacientes/{id}/convenios (sempre cria um novo) e PUT /pacientes/{id}/convenios/{vinculoId} (o vinculoId vem de GET /pacientes/{id}/convenios; parcial — campo omitido mantém). Corrigir dados do paciente: PUT /pacientes/{id} é parcial desde 01–02/10/2026 — envie só o que muda; contato e convenioPlano, se enviados, substituem a lista (o que tem id e não veio é inativado). Anexos: POST /pacientes/{id}/anexos (multipart, campo file, até 10 arquivos JPG/PNG/PDF de até 10 MB).
18. Passo 14 — Parâmetros e permissões
Por último, as regras de negócio: /parametros/orcamento (inclui desabilitarBloqueioFarol), /parametros/financeiro, /parametros/estoque (reserva de medicamento), /parametros/avisos/{chave}, /parametros/acolhimento, /parametros/servicos-online/*, /parametros/termo, alçadas de desconto e de compra por colaborador, e o controle de acesso a dashboards. Sempre faça o GET antes do PUT e reenvie o objeto completo (só /parametros/desconto declara que omitido mantém; em /parametros/financeiro, omitir categoriaPagamentoId/centroDeCustoId grava null). A chave de API nunca é tratada como administrador: níveis que exigem aprovação administrativa não são conferidos por essas rotas. Perfis e permissões de tela dos usuários ficam na tela do sistema. Referência: Referência — Parâmetros.
19. Migração de histórico
| O quê | Como | Cuidados |
|---|---|---|
| Pacientes em lote | POST /pacientes/bulk (50 por vez) | Lotes sequenciais (429 se houver outro em andamento). Em 207, reenvie só os itens com erro. |
| Vínculos de convênio | No próprio corpo (convenioPlano) ou POST /pacientes/{id}/convenios | Carteirinha já em uso → 400. Para corrigir, use PUT …/convenios/{vinculoId} — não crie de novo. |
| Anexos | POST /pacientes/{id}/anexos (multipart) | Até 10 arquivos, JPG/PNG/PDF, 10 MB cada; tipoAnexoId opcional. Não há exclusão pela API. |
| Atendimentos | 1) POST /atendimentos (pacienteId, colaboradorId, empresaId, servicoId, convenioId, dataAtendimento) → devolve atendimentoId, agendamentoId, prontuarioId2) PUT /atendimentos/{id} com responsavelId e horarioInicio = data/hora real — repita pacienteId e empresaId (a rota não declara que omitido mantém) | O atendimento grava sempre "agora" — o passo 2 é obrigatório para a data real. Cria por trás um agendamento sintético e um prontuário vazio. Não finaliza atendimento nem baixa estoque. |
| Prontuário | POST /atendimentos/prontuario (prontuarioId, conteudo); mais de uma evolução: POST /atendimentos/novo-prontuario e depois grave o texto | Sobrescreve sem guardar versão anterior — grave o texto final. Não há exclusão de prontuário. |
| Conferência | GET /atendimentos/historico?pacienteId=… | pacienteId é obrigatório nesta rota (sem ele a leitura varreria o histórico inteiro da clínica). Filtros: medico, servico, dataAtendimento. |
curl -s -X POST "$BASE/atendimentos" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"pacienteId": 231, "colaboradorId": 60, "empresaId": 54, "servicoId": 45, "convenioId": 12,
"dataAtendimento": "2025-03-14T10:00:00.000Z"
}'
# → { "atendimentoId": 4400, "agendamentoId": 8801, "prontuarioId": 9001 }
curl -s -X PUT "$BASE/atendimentos/4400" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"responsavelId": 60, "pacienteId": 231, "empresaId": 54, "horarioInicio": "2025-03-14T10:00:00.000Z"
}'
curl -s -X POST "$BASE/atendimentos/prontuario" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"prontuarioId": 9001, "conteudo": "Texto clínico migrado do sistema anterior."
}'
curl -s "$BASE/atendimentos/historico?pacienteId=231" -H "Authorization: Bearer $TOKEN"
20. Operação contínua (resumo)
| Área | Rotas principais | Observações |
|---|---|---|
| Agenda | GET /agendamentos/datas/disponiveis, POST /agendamentos/horarios/disponiveis, GET /agendamentos/locais/disponiveis, POST /agendamentos, PATCH /agendamentos/{id}/cancelar | GET /agendamentos exige data (um dia por chamada — para sincronizar vários dias, uma chamada por dia) e pagina de verdade (page/pageSize até 200; filtros pacienteId, profissionalId, statusId). Criar exige responsavelId, paciente.id, idGrade, data, statusId, procedimentos[]; sem pagamento no ato; consome o limite mensal do plano. Cancelar exige motivoCancelamentoId (GET /agendamentos/motivo-cancelamento). |
| Orçamento | POST /orcamentos, PUT /orcamentos/{id}, PUT /orcamentos/status/{idOrcamento}/{idStatus}, anexos | Listagem GET /orcamentos paginada, com filtros id, pacienteId, pacienteCpf, pacienteNome, statusId, createdAtDe/createdAtAte (com pacienteId o formato do item muda). PUT /orcamentos/{id}: parcial (procedimentos enviado substitui a lista sem perder sessões já realizadas). Status automáticos (Vencido, Pago, Agendado, Concluído, Renegociado) são recusados (422) na troca manual de status; a troca automática ainda não está ativa (#656). Pagamento no ato permitido (pode emitir NFS-e). 422 se o Farol exigir aprovação e não houver token/pendência. A descrição da rota diz que orçamento aprovado não pode ter procedimentos/valores editados (registrar pagamento continua funcionando); na tela, desde 25/09/2026, travam a edição os status Recusado e Aprovado pela Assistência (Aprovado pelo Paciente/Convênio seguem editáveis) — trate a recusa da API como a palavra final. Financeiro único (orçamentos criados desde 25/09/2026): todas as sessões compartilham uma movimentação financeira com o valor total do orçamento; depois de pago, o valor trava (sem alterar valor nem dar desconto). |
| Faturamento | /faturamento/guias…, /divergencias, /recebimento, /glosas | Pré-faturamento (edição completa da guia, confirmar), faturar diferença, registrar/devolver recebimento, gravar glosa por item. Valores: algumas leituras de faturamento devolvem centavos ou string (ex.: GET /faturamento/guias/servico/{guiaFilha}, GET /faturamento/glosas/guia/{guiaMae}) — leia a descrição da rota antes de somar ou comparar. |
| NFS-e | POST /nfse/notas (calcula) → POST /nfse/notas/{id}/emitir; cancelar, substituir, contingência, tomadores | Calcular não envia nada à prefeitura; idempotente via header Idempotency-Key. Emitir consome o limite mensal do plano. |
| Estoque | /estoque/entrada, /saida, /transferencia, /saldo-produtos, /previsao | Escritas exigem responsavelId; saída e transferência exigem lote (ou null) desde 28/09/2026. GET /estoque paginado com filtros produtoId/localizacaoId. |
| Financeiro | /financeiro/movimentacoes (+ /bulk), POST /financeiro/pagamentos/confirmacao | Sem exclusão pela API; criar/editar pode disparar NFS-e automática. A confirmação de pagamento (Pix/link) é idempotente (jaConfirmado: true). |
Detalhes: Referência — Operação.
21. Roteiro para IA (prompt de implantação)
Cole o bloco abaixo como instrução de um agente de IA que vai implantar ou migrar uma clínica. Ele resume a ordem e as regras de ouro desta página.
Você vai implantar a clínica no Rabi Sistemas pela API externa.
BASE = https://api.hmg.rabisistemas.dev/api/v1/integrations (ensaio) — produção só com autorização.
Header em toda chamada: Authorization: Bearer rbt_SEU_TOKEN (recomendado: token rbt_ "Implantação e
manutenção" da clínica; alternativa: a chave rbk_ do time Rabi). Leia o token de variável de ambiente.
Nunca registre a chave/token em log, documento, chamado, e-mail ou conversa salva.
A API grava direto: o "modo consulta" das telas de convênio (#632) não vale para ela.
ORDEM OBRIGATÓRIA (não pule, não inverta):
0. GET /auxiliares/* → monte o dicionário de ids. Tipo faltando? PARE e peça ao implantador
para criar pela tela (a API não cria auxiliares). Peça também os ids que só existem na tela
(especialidades, categorias de pagamento, contas/caixas, centros de custo, motivos de estoque).
1. POST /empresas → guarde empresaId
2. POST /depositos(/bulk) → 1 depósito mínimo POR UNIDADE (antes dos locais!)
3. POST /locais → depositoPadraoSaidaId = depósito ATIVO (senão 422)
4. POST /operadoras/bulk, /fornecedores/bulk, /fabricantes/bulk → guarde ids (e planos)
5. POST /taxas/bulk → TAXAS ANTES DE CONVÊNIOS e tabelas de preço
6. POST /produtos/bulk → PRODUTOS ANTES DE SERVIÇOS (exige depósito e fabricante)
7. POST /equipamentos/bulk
8. POST /servicos → SUBSERVIÇOS PRIMEIRO; depois os pais com servicosRelacionados
taxas em servicoTaxa: [{taxaId, quantidade}] (NÃO taxaServicoId/valorTaxaServico);
produtoIds/equipamentoIds/servicosRelacionados: ID ou objeto
9. POST /colaboradores/bulk → e POST /colaboradores/{id}/usuario para quem precisa de login
9b. POST /tabelas-preco + /tabelas-preco/produtos/bulk
10. POST /convenios(/bulk) → dados; depois PUT /convenios/{id}/planos, /especialidades (Atende de TODAS
as especialidades cobertas ANTES de serviços/colaboradores — sem isso
o upsert recusa Utiliza no serviço; #628),
/taxas, /produtos, /servicos, /colaboradores (um por vez)
10b. POST /grades-colaborador (com servicos[] e convenio[]), /grades-equipamento
11. GET /convenios/{id}/farol/servicos → lista de serviços; para cada serviço a conferir:
GET /convenios/{id}/farol/itens/{servicoRaizId} → árvore com conta_no_total e motivo_exclusao
12. Estoque (entradas com valorCompra; saída/transferência com lote ou lote: null) e financeiro
13. POST /pacientes/bulk (+ vínculos e anexos)
14. Parâmetros (GET antes de PUT)
REGRAS DE OURO:
- Vazio ≠ zero. Sem valor = omitir ou null. 0 = zero de verdade. NUNCA use 0.01 como "sem valor".
- Utiliza = o convênio cobre. Sem Utiliza = custo sem receita.
- Taxas, produtos e subserviços com Utiliza SEMPRE entram na conta do serviço.
somarItems decide só o valor próprio do serviço.
- valorInternoConvenio sozinho NÃO fecha pacote. Preço fechado = valorInternoConvenio + pacote: true
no serviço + zerarValor: true em cada item incluso (produtos/taxas/subserviços).
- Zerar é por item e não desce em cascata; só age em pacote de preço fechado.
- PUT PARCIAL (desde 01-02/10/2026) em /servicos, /convenios, /pacientes, /colaboradores, /orcamentos,
grades, /financeiro/movimentacoes e /faturamento/guias: campo omitido MANTÉM, null LIMPA,
lista omitida mantém, lista enviada SUBSTITUI ([] apaga). Envie só o que muda; para trocar uma
lista, mande a lista inteira (parta do GET). Abas PUT /convenios/{id}/... = upsert (omitido mantém).
PUT sem declaração no Swagger (produtos, taxas, equipamentos, locais, depósitos, fornecedores,
fabricantes) e /empresas/{id}: SOBRESCRITA — faça GET e reenvie o objeto completo.
- Lotes: máx. 50 (tabela interna 200, tomadores NFS-e 100). Um lote por vez por recurso.
207 → reenvie SÓ os itens com ERRO/NAO_PROCESSADO. 429 → espere e tente de novo.
- 409 → o registro já existe: busque pelo GET e reutilize o id. 422 → falta pré-requisito (ordem!).
- 401 → chave rejeitada (ausente, errada, expirada, revogada): PARE e avise. 403 → sem permissão:
PARE e avise qual falta (campo escopoFaltante) — com rbt_, o implantador libera em "Editar permissões". 503 → falha de rede/tempo: repita com espera progressiva (2 s, 4 s, 8 s).
- Validade: leia o header X-ApiKey-Expires-At na 1ª resposta (rbk_ e rbt_); se vencer antes do fim do
trabalho, avise o implantador (rbt_: Renovar na tela de Integrações — o valor antigo deixa de valer;
rbk_: chave nova pelo time Rabi).
- Listagens usam {dados, page, pageSize, total, totalPages}; percorra até page = totalPages (não pare
quando dados vier menor que pageSize). Rotas cuja resposta o Swagger descreve como "Array direto"
(ex.: /atendimentos/historico, /estoque/historico/{id}) não têm envelope.
GET /agendamentos EXIGE data (um dia por chamada). Grades: filtre por colaboradorId/equipamentoId,
localId e vigenteEm.
- Valores em reais, EXCETO leituras de faturamento sinalizadas na descrição da rota (centavos ou
string, ex.: /faturamento/guias/servico/{guiaFilha}, /faturamento/glosas/guia/{guiaMae}).
Leia a descrição da rota antes de somar/comparar.
- Farol: GET /convenios/{id}/farol/itens/{servicoRaizId} (um serviço, sem paginação) ou
GET /convenios/{id}/farol/itens?apenasAtivosNoConvenio=true&servicoAtivo=true (vários).
Cada linha traz conta_no_total, motivo_exclusao, margem_servico_pct e farol_servico.
efetivo.totalConvenio NÃO está na API externa: o total do serviço é receita_total_servico
(linha nivel = 0) ou receita_total em /farol/servicos.
- DELETE /produtos/{id} ou /taxas/{id} de item em composição de serviço ativo → 409 com a lista
em "servicos" (#626). Substitua o item nesses serviços, depois desative.
- Produto: codigoEAN e codigoNCM como TEXTO (preserva zeros). Tabela interna: priceType1..3 em REAIS.
- Repasse do colaborador: item sem servico/produto/taxa = linha geral (no máximo 1 por tipo).
- Gravou algo pela API antes de 28/09/2026 17:43? Faça a CONFERÊNCIA RETROATIVA (pacientes/bulk,
lote de preços, PUT de movimentação/fornecedor, UF, estoque sem lote) antes de seguir.
- 404 em rota que deveria existir = caminho/método errado (desde 26/09 rota inexistente dá 404,
não mais 401 "jwt malformed"). 404 com rota certa = id não existe nesta clínica.
- Ao final, entregue: tabela de ids criados, itens com erro e o resultado do Farol por convênio
(liste linhas vermelhas e roxas com o motivo provável).
21.1 Checklist de fechamento
- ☐ Toda unidade tem depósito ativo e todo local aponta para um depósito ativo.
- ☐ Nenhum valor
0.01gravado como "sem valor" (serviços, taxas, produtos das abas do convênio). - ☐ Todo serviço composto foi criado depois dos seus subserviços e produtos (
GET /servicos/{id}mostra a composição). - ☐ Cada convênio tem as 6 abas conferidas por
GETe o Farol lido (farol/servicose, por serviço,farol/itens/{servicoRaizId}) — vermelhos e roxos explicados; itens fora da conta com omotivo_exclusaoesperado pelo contrato. - ☐ Nenhum produto/taxa foi desativado enquanto ainda fazia parte da composição de um serviço ativo (desde 02/10/2026 a API recusa com 409; confira desativações anteriores).
- ☐ Serviços com taxas gravados com
servicoTaxa(nuncataxaServicoId/valorTaxaServico) e a composição conferida porGET /servicos/{id}e pelo Farol. - ☐ Cada convênio com Atende marcado em todas as especialidades que cobre (#628 — vale no cadastro do convênio).
- ☐ Se houve gravação pela API antes de 28/09/2026 17:43: conferência retroativa feita.
- ☐ Colaboradores que usam o sistema têm login (
POST /colaboradores/{id}/usuario). - ☐ Toda correção por
PUTfoi conferida porGETdepois: nas rotas parciais, só o que mudava foi enviado (e listas trocadas foram enviadas inteiras); nas rotas sem declaração, o objeto completo. - ☐ Valores lidos de rotas de faturamento foram interpretados conforme a descrição da rota (reais × centavos/string).
- ☐ A validade do token da integração contínua está registrada, com alerta antes do vencimento (
rbt_: renovar na tela de Integrações;rbk_: data doX-ApiKey-Expires-At, renovação pelo time Rabi). - ☐ O token de implantação foi revogado —
rbt_em Configurações › Parâmetros › Integrações (vale na hora);rbk_pelo time Rabi no portal comercial — ou reduzido às permissões da integração contínua. - ☐ (Se a clínica usa a IA TalkMe) grades com serviços e convênios,
utiliza/Atende no convênio e convênio ativo nas unidades certas — a consulta de disponibilidade da IA (#633) usa esse cadastro desde 09/10/2026. - ☐ Repasse dos profissionais cadastrado (com a linha geral, se for o caso) e custos extras do convênio cadastrados pela tela — o Farol só fica realista com eles (desde 12/10/2026).
Continue por aqui: Visão geral · Referência — Cadastros · Erros e boas práticas · Guia de Implantação (pela tela) · Preços — Guia do Implantador