Paciente
O Patient carrega os dados demográficos e
administrativos de quem recebe cuidado. É o recurso central da integração: quase todo
outro recurso — atendimento, condição, plano de cuidado — referencia um paciente.
Campos
A coluna No NiloCare traz o rótulo com que o dado aparece para a equipe de cuidado. São rótulos, não caminhos de navegação: a tela pode ser reorganizada, o rótulo é o que permite conferir se o dado chegou onde você esperava.
1 Todo paciente pertence a pelo menos um grupo, mas o payload pode omiti-lo se a
sua unidade de cuidado tiver grupo padrão configurado. Veja Grupos.
2 Obrigatórias no envio, e preenchidas com o padrão da sua unidade de cuidado
quando omitidas. Sem valor enviado e sem padrão configurado, a escrita é recusada.
3 O system do CPF vem configurado como identificador único do paciente por
padrão, e nessa configuração o CPF é obrigatório. Ele só é opcional se a sua implantação
usar outro identificador único — veja CPF como identificador único, adiante.
4 gender é o único campo do recurso que não é preservado numa atualização
parcial: omiti-lo grava other por cima do sexo atual. Reenvie-o em toda escrita — veja
Sexo.
A URL completa de cada extensão está em Extensões — nesta página elas aparecem só pelo nome final.
Sexo é de preenchimento obrigatório no cadastro pela interface, mas gender é opcional
na API — e essa diferença tem uma consequência que foge à regra da atualização parcial.
Um Patient enviado sem gender grava other, inclusive num paciente que já tem sexo
registrado. Reenvie gender em toda escrita, mesmo quando o objetivo é atualizar outro
campo. Veja Sexo.
Cadastrar ou atualizar
Não há endpoint separado para criar e atualizar. O mesmo POST faz os dois, e quem
decide é o identifier: se já existir um paciente com aquele par system + value,
ele é atualizado; se não existir, é criado.
O system é o namespace do seu sistema e o value é a chave do paciente lá dentro.
Reenviar o mesmo payload não gera duplicata, o que torna seguro reprocessar uma carga.
Criar um paciente pode disparar uma mensagem de boas-vindas por WhatsApp e liberar o primeiro agendamento — comportamento controlado pelas extensões obrigatórias, que assumem o padrão da sua unidade quando você as omite. Antes da primeira carga em volume, confirme esses padrões. Veja Efeitos colaterais.
Trocar o system de um paciente já integrado faz a Nilo tratá-lo como um paciente novo.
O histórico fica partido em dois registros e não há como juntá-los depois pela API.
Um cadastro mais completo aceita CPF, contato, endereço, unidade de cuidado e as extensões Nilo:
A resposta devolve o recurso como ficou gravado:
Guarde o id: é por ele que se faz a leitura direta do paciente.
Repare que a resposta traz mais identificadores do que você enviou. A Nilo devolve o seu
identifier junto com os dela — o id interno do paciente
(…/NamingSystem/hippocrates-api--patient), o token
(…/NamingSystem/care-api--patient-v2-token), o id legado
(…/NamingSystem/care-api--patient-v2) e o CPF, quando houver. Todos servem para buscar;
o seu continua sendo o único que você precisa guardar.
A atualização é parcial. Campo ausente ou enviado como null preserva o valor atual —
não existe, por esta rota, como apagar um dado já gravado. São três as exceções: o nome
social, removido quando o name com use: usual vem com period.end preenchido; a lista
de grupos, substituída por inteiro quando contained é enviado; e gender, que omitido
grava other por cima do valor atual — veja Sexo.
Buscar
A resposta é sempre um Bundle do tipo searchset, mesmo quando há um único resultado:
Busca sem resultados não é erro: volta 200 com um Bundle cujo entry é uma lista
vazia. Trate a ausência de resultados pela lista vazia, não esperando um 404.
Parâmetros de busca suportados
* O {id} do filtro organization é o id da unidade no store FHIR, não o
identificador que você usa no seu sistema. Pegue-o do managingOrganization.reference de
um paciente já lido.
Estado civil, grupos e as extensões Nilo não são filtráveis: o FHIR R4 não define
search parameters para eles no Patient. E não há caminho pelo outro lado: o
grupo de pacientes não carrega a lista de membros. Para
saber quem está num grupo, percorra os pacientes e leia o contained de cada um.
A busca mais comum na prática é pelo identificador do seu próprio sistema, que usa a
sintaxe system|value:
Paginação e recorte por data
Além dos search parameters do Patient, a busca aceita três parâmetros de controle:
A resposta não traz contagem total. Para percorrer todas as páginas, siga o link com
relation: next até ele deixar de vir — a URL já embute o _page_token da página
seguinte, e é o único jeito confiável de paginar:
Ler por ID
A leitura por ID responde 404 quando o id não existe.
A leitura por ID não devolve o recurso na raiz da resposta. Ela devolve uma entrada
com a mesma forma das entradas de Bundle.entry — fullUrl, resource e search — e o
paciente está em resource. É a diferença mais fácil de errar entre esta rota e a busca:
a busca envolve as entradas num Bundle, esta devolve uma entrada solta, mas em nenhuma
das duas o Patient está no topo.
Valores aceitos
Sexo
gender segue os códigos administrativos do FHIR, mas só dois sobrevivem à gravação:
A última linha é a pegadinha: gender é o único campo do Patient que não segue a regra
da atualização parcial. Omitido, ele não preserva o sexo atual — grava other por cima.
Um payload de correção de endereço, ou o exemplo Adicionar CPF desta página, apaga o
sexo do paciente se não trouxer gender.
Leia o paciente antes de atualizá-lo e reenvie o gender que voltou. Na leitura ele nunca
vem nulo, então não há caso em que você não tenha o valor para reenviar.
Identidade de gênero
Para registrar identidade de gênero, use a extensão patient-genderIdentity, que tem
vocabulário próprio:
Num paciente novo, qualquer outro código — ou a ausência da extensão — é gravado como
non-disclose. Num paciente que já existe, o valor atual é preservado.
Estado civil
maritalStatus reconhece quatro códigos de
v3-MaritalStatus e um de
v3-NullFlavor:
Num paciente novo, qualquer outro código cai em UNK, e é UNK que volta na leitura.
Num paciente que já existe, um código não reconhecido preserva o estado civil atual em vez
de sobrescrevê-lo.
Efeitos colaterais
Uma escrita de Patient faz mais do que gravar o cadastro.
patient-sendWelcomingMessage com valueBoolean: true envia uma mensagem de WhatsApp
ao paciente no momento do cadastro. Numa carga inicial de milhares de pacientes, isso são
milhares de mensagens. A extensão é obrigatória, mas assume o padrão da sua unidade quando
omitida — não deixe esse padrão decidir por você numa migração.
patient-createOnboardingScheduling com valueBoolean: true libera o paciente para
agendar o primeiro atendimento assim que o cadastro entra. Vale a mesma cautela.
Enviar address cria ou atualiza o endereço do paciente como registro próprio. Só o
primeiro item de address é lido; os demais são descartados sem aviso.
address.line é posicional na escrita — line[0] logradouro, line[1] número,
line[2] complemento — mas a leitura omite os itens vazios em vez de devolvê-los como
string vazia. Num paciente sem logradouro, o número volta em line[0]; reenviar essa
resposta sem tratar grava o número como logradouro. Ao montar uma escrita a partir de uma
leitura, remonte line pelos rótulos, não pela posição em que veio.
Enviar contained substitui a lista de grupos do paciente pela lista enviada — não
acrescenta. Para adicionar um grupo, reenvie os que o paciente já tem mais o novo; para
removê-lo, reenvie a lista sem ele. Veja Grupos.
Regras de escrita e validações
Recusa é sempre 400 com um OperationOutcome: issue[].expression aponta o campo
culpado e issue[].details.text explica o motivo.
Um payload que contenha a URL de outro ambiente da Nilo é recusado — a mensagem fala
de “identifier from a Nilo environment that is not the current environment”. Como as URLs
das extensões Nilo e os system dos identificadores internos embutem o host do ambiente,
é o erro esperado de quem copia um payload lido em produção e o reenvia em homologação.
Ao migrar um exemplo entre ambientes, troque o host em todas as URLs, ou remova os
identificadores e extensões que a Nilo devolveu e mande apenas os seus.
O que depende da implantação
Três decisões são configuradas por unidade de cuidado no momento da implantação, e mudam o que a API exige de você. Se não souber como a sua está, fale com o time antes de montar a carga.
Identificadores
Ao menos um identifier é obrigatório, e o system enviado precisa estar entre os
namespaces habilitados para a sua unidade — é por ele que a Nilo decide entre criar e
atualizar. Enviar só identificadores de system desconhecido é recusado, em vez de
criar um paciente duplicado:
CPF como identificador único
Por padrão, o system do CPF é o identificador único do paciente. É essa configuração
que torna o CPF obrigatório no cadastro: enquanto ela vale, um payload sem CPF não tem por
onde ser reconhecido e é recusado com o mesmo OperationOutcome da seção anterior — mesmo
que traga o identificador do seu próprio sistema.
Enquanto o CPF for o identificador único da sua implantação, não há como cadastrar um paciente sem CPF por esta API.
Nem toda operação tem o CPF de todo paciente. Se a sua precisa cadastrar sem ele — usando o identificador do seu sistema como chave —, essa configuração pode ser trocada, mas não pela API: abra um ticket no Suporte pedindo a mudança do identificador único da sua unidade de cuidado.
Depois da troca, o CPF passa a ser opcional e continua aceito como identificador
adicional, com as mesmas regras de formato e de use descritas abaixo.
CPF
O CPF é um identifier como os outros, mas com tratamento próprio: use o system
https://servicos.receita.fazenda.gov.br/servicos/cpf/ e envie exatamente 11 dígitos, sem
pontos nem traços.
Para acrescentá-lo a um paciente que já existe, mande o identificador que encontra o
paciente, o CPF e o gender atual do paciente:
Como a atualização é parcial, o resto do cadastro fica intacto — nome, grupo e as
extensões obrigatórias não precisam ser reenviados. O gender é a exceção: omiti-lo grava
other por cima do sexo do paciente, e por isso ele acompanha o payload mesmo não sendo o
dado que se quer mudar. Veja Sexo. O CPF volta na resposta como mais um
identificador:
O use: official não é decorativo: é ele que autoriza escrever por cima de um CPF já
gravado. Um CPF com qualquer outro use só entra se o paciente ainda não tiver CPF nenhum —
é assim que se envia um dado de baixa confiança sem sobrescrever o que já foi verificado.
Se o payload trouxer mais de um identificador de CPF, apenas o primeiro utilizável é lido.
Note que o exemplo acima manda o identificador do seu sistema junto com o CPF. O CPF
sozinho só encontra o paciente se o system da Receita estiver entre os namespaces
habilitados para a sua unidade de cuidado.
Quando o system do CPF está habilitado para a sua unidade, ele passa a ser também a
chave externa do paciente no NiloCare, à frente do identificador do parceiro. Isso vale
para pacientes já cadastrados: a chave externa deles é trocada na escrita seguinte.
Nome
Um paciente novo precisa de um name com use: official que tenha text, given ou
family; a Nilo prefere o text e, na falta dele, junta given e family. Um name
com use: usual vira o nome social. Se o payload trouxer mais de um name do mesmo
use, vale o último da lista.
Para remover o nome social, reenvie o name com use: usual e um period.end — qualquer
data serve, é a presença do campo que apaga o valor:
Datas
O FHIR aceita datas parciais que o NiloCare não representa. Uma birthDate enviada como
2022-12 é completada para 2022-12-01 ao ser gravada. Envie a data completa quando você
a tiver, para que a leitura devolva o que você espera.
Grupos
Todo paciente pertence a pelo menos um grupo. Há três formas de indicar isso, e elas não se combinam:
A URL completa de cada uma está em Extensões.
O Group referenciado precisa já existir — cadastre-o antes de referenciá-lo aqui.
Um identificador que não resolve recusa a escrita inteira, e mandar grupo em contained
e em extension ao mesmo tempo também.
Enviar contained substitui a lista inteira de grupos do paciente. Para acrescentar um
grupo, reenvie os grupos que o paciente já tem junto com o novo:
Para remover, reenvie a lista sem o grupo que sai. Omitir contained por completo
preserva os grupos atuais — não os apaga. E num paciente que já existe as duas extensões
de grupo não têm efeito: só a criação as considera.
Sem grupo em contained, sem extensão de grupo e sem grupo padrão configurado para a
unidade, a criação é recusada:
Na leitura, os grupos voltam de duas formas ao mesmo tempo: contained traz todos e a
extensão patient-cohort traz apenas o primeiro. Leia os grupos do contained; a
extensão está lá por compatibilidade e não representa o conjunto.
Unidade de cuidado
managingOrganization precisa apontar para uma unidade já cadastrada. Omitindo o campo,
a Nilo mantém a unidade que o paciente já tem ou, para um paciente novo, usa a unidade
padrão do care provider. Sem unidade no payload e sem unidade padrão configurada, a
criação falha:
Esta integração representa uma unidade de cuidado por paciente. Um paciente que esteja
em mais de uma unidade no NiloCare não sincroniza: a leitura falha em vez de devolver a
primeira, e o erro que chega é um 400 genérico, sem apontar a causa. Se a sua base tem
pacientes em várias unidades, fale com o time antes de integrá-la.
Telefone
O telefone passa por validação de elegibilidade para WhatsApp, e um número reprovado
recusa a escrita inteira. Números de baixa confiança devem ir com use: old ou
use: temp: nesse caso o número é apenas descartado, sem derrubar a requisição nem
sobrescrever um contato mais atual.
Com mais de um telecom de telefone, um use: old é ignorado quando existe outro número,
e o use que corresponde à tag de telefone verificado da sua implantação tem precedência
sobre os demais.
Status
Os status de paciente não são um vocabulário fixo: cada care provider tem os seus,
definidos na implantação. Não há como descobri-los pela API — peça a lista ao time antes
de usar a extensão patient-status.
active e a extensão …/StructureDefinition/patient-status descrevem a mesma coisa por
caminhos diferentes. Enviando os dois, eles precisam concordar: um active: true com um
status de categoria inativa (ou o contrário) é recusado. O id da extensão também precisa
existir entre os status do seu care provider.
Enviando só active num paciente novo, a Nilo escolhe o status padrão ativo ou inativo da
unidade. Num paciente que já existe, o status atual é mantido quando concorda com o
active enviado, e trocado pelo padrão da categoria apenas quando discorda — um
active: false num paciente ativo o move para o status inativo padrão, sem escolher entre
os vários status inativos que o seu care provider possa ter.
Enviando nenhum dos dois, um paciente novo nasce com o status padrão ativo e um paciente existente mantém o que já tinha.
Campos ignorados
communication é sempre gravado como pt-BR, independentemente do que for enviado. A
extensão …/StructureDefinition/patient-paths é apenas devolvida — é o atalho para a
ficha do paciente no NiloCare. Extensões fora do contexto Nilo não têm efeito no cadastro,
mas ficam gravadas no recurso e voltam nas leituras seguintes — veja
Extensões.
Este endpoint não remove pacientes: a escrita nunca responde 204. A remoção acontece do
lado Nilo e é propagada para o store FHIR pela sincronização, não por esta API.
O que a integração não cobre
A ficha do paciente no NiloCare tem campos que não têm representação no Patient e
por isso não podem ser preenchidos nem lidos por esta API. Eles só existem pela interface:
-
Tipo sanguíneo e Deficiências
-
Escolaridade, Profissão e Com quem mora
-
Cor ou raça autodeclarada
-
Detalhes pessoais relevantes (texto livre)
-
Nome da mãe
Enviar esses dados dentro de extensões próprias não os faz aparecer na ficha: a extensão é gravada no recurso FHIR e devolvida nas leituras, mas o cadastro do paciente não a lê.
O plano de saúde do paciente não fica no Patient — é o recurso
Coverage, gravado à parte e ligado ao paciente por
beneficiary.

