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.

CampoObrigatórioO que significaNo NiloCare
identifiersim, ao menos umChaves do paciente. É por aqui que a API decide entre criar e atualizar
identifier (CPF)sim por padrão 3CPF, exatamente 11 dígitosCPF
name[use=official]sim na criaçãoNome legal. Vale o text; na falta dele, given + familyNome paciente
name[use=usual]nãoNome social ou apelidoNome Social (para pessoas trans, travestis e transexuais)
birthDatenãoData de nascimentoData de Nascimento
gendernão, mas reenvie 4Sexo administrativo. Só male e female são gravadosSexo
maritalStatusnãoEstado civilEstado civil
telecom[system=phone]nãoCelular do paciente. Passa por validação de WhatsAppCelular com Whatsapp
telecom[system=email]nãoE-mail de contatoEmail
address[0].line[0]nãoLogradouroLogradouro
address[0].line[1]nãoNúmero. Ausente, é gravado como S/NNúmero
address[0].line[2]nãoComplementoComplemento
address[0].districtnãoBairroBairro
address[0].citynãoCidadeCidade
address[0].statenãoEstadoEstado
address[0].postalCodenãoCEPCEP
address[0].countrynãoPaís
deceasedDateTimenãoData e hora do óbito
managingOrganizationnãoUnidade de cuidado responsável pelo pacienteUnidade de cuidado
contained[Group]sim, com ressalva 1Grupos a que o paciente pertenceGrupos de pacientes
activenãoSe o cadastro está em uso. Traduz para o status do pacienteStatus
extension patient-statusnãoStatus do paciente pelo id de um status do seu care providerStatus
extension patient-isLeadnãotrue = pré-cadastro, ainda pendente de aceite dos termos de usoJá aceitou os termos de uso para ser paciente?
extension patient-sendWelcomingMessagesim, com ressalva 2Dispara ou não a mensagem de boas-vindas ao cadastrarEnviar mensagem de boas vindas?
extension patient-createOnboardingSchedulingsim, com ressalva 2Libera o paciente para o primeiro agendamentoLiberar agendamento de onboarding?
extension patient-genderIdentitynãoIdentidade de gênero, num vocabulário próprioIdentidade de gênero
extension patient-religionnãoEspiritualidade declarada, em texto livreEspiritualidade
extension patient-cadavericDonornãoSe o paciente é doador de órgãosDoador de órgãos
communicationsó respostaIdioma de contato. Sempre pt-BR
extension patient-pathssó respostaAtalho para a ficha do paciente no NiloCare

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.

POST
/fhir/resources/Patient
1curl -X POST https://landing-zone-api.nilo.services/fhir/resources/Patient \
2 -H "x-api-key: <apiKey>" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "identifier": [
6 {
7 "system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
8 "value": "39053344705",
9 "use": "official"
10 },
11 {
12 "system": "https://www.acmesaude.com.br/integracao/paciente/",
13 "value": "507823709",
14 "use": "usual"
15 }
16 ],
17 "resourceType": "Patient",
18 "extension": [
19 {
20 "url": "https://landing-zone-api.nilo.services/fhir/resources/Group",
21 "valueIdentifier": {
22 "system": "https://www.acmesaude.com.br/integracao/grupo/",
23 "use": "usual",
24 "value": "diabeticos-tipo-2"
25 }
26 },
27 {
28 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-sendWelcomingMessage",
29 "valueBoolean": true
30 },
31 {
32 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-createOnboardingScheduling",
33 "valueBoolean": true
34 }
35 ],
36 "name": [
37 {
38 "family": "Silveira",
39 "given": [
40 "João"
41 ],
42 "use": "official"
43 }
44 ]
45}'

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:

POST
/fhir/resources/Patient
1curl -X POST https://landing-zone-api.nilo.services/fhir/resources/Patient \
2 -H "x-api-key: <apiKey>" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "identifier": [
6 {
7 "system": "https://www.acmesaude.com.br/integracao/paciente/",
8 "value": "507823709",
9 "use": "usual"
10 },
11 {
12 "system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
13 "value": "39053344705",
14 "use": "official"
15 }
16 ],
17 "resourceType": "Patient",
18 "active": true,
19 "address": [
20 {
21 "city": "São Paulo",
22 "country": "Brasil",
23 "district": "Pinheiros",
24 "line": [
25 "Rua das Acácias",
26 "120",
27 "Apto 42"
28 ],
29 "postalCode": "01415000",
30 "state": "São Paulo",
31 "type": "both",
32 "use": "home"
33 }
34 ],
35 "birthDate": "1974-12-25",
36 "contained": [
37 {
38 "resourceType": "Group",
39 "identifier": [
40 {
41 "system": "https://www.acmesaude.com.br/integracao/grupo/",
42 "value": "diabeticos-tipo-2",
43 "use": "usual"
44 }
45 ],
46 "type": "person",
47 "actual": true,
48 "name": "Diabéticos tipo 2"
49 }
50 ],
51 "extension": [
52 {
53 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-isLead",
54 "valueBoolean": false
55 },
56 {
57 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-sendWelcomingMessage",
58 "valueBoolean": true
59 },
60 {
61 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-createOnboardingScheduling",
62 "valueBoolean": true
63 },
64 {
65 "url": "http://hl7.org/fhir/StructureDefinition/patient-genderIdentity",
66 "valueCodeableConcept": {
67 "coding": [
68 {
69 "code": "male",
70 "display": "male",
71 "system": "http://hl7.org/fhir/gender-identity"
72 }
73 ]
74 }
75 },
76 {
77 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-religion",
78 "valueCodeableConcept": {
79 "text": "Católica"
80 }
81 },
82 {
83 "url": "http://hl7.org/fhir/StructureDefinition/patient-cadavericDonor",
84 "valueBoolean": true
85 }
86 ],
87 "gender": "male",
88 "managingOrganization": {
89 "identifier": {
90 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/sorting-hat-api--care-unit",
91 "value": "4",
92 "use": "usual"
93 },
94 "type": "Organization"
95 },
96 "maritalStatus": {
97 "coding": [
98 {
99 "code": "M",
100 "display": "Married",
101 "system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus"
102 }
103 ]
104 },
105 "name": [
106 {
107 "family": "Silveira",
108 "given": [
109 "João",
110 "Pedro"
111 ],
112 "text": "João Pedro Silveira",
113 "use": "official"
114 },
115 {
116 "text": "Joana Silveira",
117 "use": "usual"
118 }
119 ],
120 "telecom": [
121 {
122 "system": "phone",
123 "use": "mobile",
124 "value": "5511987654321"
125 },
126 {
127 "system": "email",
128 "use": "home",
129 "value": "joao.silveira@example.com"
130 }
131 ]
132}'

A resposta devolve o recurso como ficou gravado:

Response
1{
2 "identifier": [
3 {
4 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/hippocrates-api--patient",
5 "value": "48210",
6 "use": "usual"
7 },
8 {
9 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--patient-v2-token",
10 "value": "0f1c2d3e-4a5b-6c7d-8e9f-a0b1c2d3e4f5",
11 "use": "usual"
12 },
13 {
14 "system": "https://www.acmesaude.com.br/integracao/paciente/",
15 "value": "507823709",
16 "use": "usual"
17 },
18 {
19 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--patient-v2",
20 "value": "31502",
21 "use": "usual"
22 }
23 ],
24 "resourceType": "Patient",
25 "active": true,
26 "contained": [
27 {
28 "resourceType": "Group",
29 "identifier": [
30 {
31 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/sorting-hat-api--cohort",
32 "value": "904",
33 "use": "usual"
34 },
35 {
36 "system": "https://www.acmesaude.com.br/integracao/grupo/",
37 "value": "diabeticos-tipo-2",
38 "use": "usual"
39 }
40 ],
41 "type": "person",
42 "actual": true,
43 "name": "Diabéticos tipo 2"
44 }
45 ],
46 "communication": [
47 {
48 "language": {
49 "coding": [
50 {
51 "code": "pt-BR",
52 "display": "Portuguese (Brazil)",
53 "system": "urn:ietf:bcp:47"
54 }
55 ]
56 },
57 "preferred": true
58 }
59 ],
60 "extension": [
61 {
62 "url": "http://hl7.org/fhir/StructureDefinition/patient-genderIdentity",
63 "valueCodeableConcept": {
64 "coding": [
65 {
66 "code": "non-disclose",
67 "display": "does not wish to disclose",
68 "system": "http://hl7.org/fhir/gender-identity"
69 }
70 ]
71 }
72 },
73 {
74 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-cohort",
75 "valueIdentifier": {
76 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/sorting-hat-api--cohort",
77 "use": "usual",
78 "value": "904"
79 }
80 },
81 {
82 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-sendWelcomingMessage",
83 "valueBoolean": true
84 },
85 {
86 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-createOnboardingScheduling",
87 "valueBoolean": true
88 },
89 {
90 "extension": [
91 {
92 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-paths-home",
93 "valueUrl": "https://acme.nilocare.app/patients/48210"
94 }
95 ],
96 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-paths"
97 }
98 ],
99 "gender": "other",
100 "id": "ba200cfa-dae0-46cf-81a0-008e3f7414b4",
101 "meta": {
102 "lastUpdated": "2026-08-06T13:04:12.905000Z",
103 "versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
104 },
105 "name": [
106 {
107 "family": "Silveira",
108 "given": [
109 "João"
110 ],
111 "text": "João Silveira",
112 "use": "official"
113 }
114 ]
115}

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

GET
/fhir/resources/Patient
1curl -G https://landing-zone-api.nilo.services/fhir/resources/Patient \
2 -H "x-api-key: <apiKey>" \
3 -d _count=50 \
4 -d _lastUpdated=eq2013-01-14 \
5 --data-urlencode _page_token=Cjj3YopYuf%2F%2F%2F%2F%2BABd%2BbgE0m...dSANQAFoLCUSM7w9VYUqaEANglLWUugQ%3D \
6 -d active=true \
7 --data-urlencode address=Acácias \
8 --data-urlencode "address-city=São Paulo" \
9 -d address-country=Brasil \
10 -d address-postalcode=01415000 \
11 --data-urlencode "address-state=São Paulo" \
12 -d address-use=home \
13 -d birthdate=1974-12-25 \
14 -d death-date=ge2024-01-01 \
15 -d deceased=true \
16 --data-urlencode email=joao.silveira@example.com \
17 -d family=Silveira \
18 -d gender=male \
19 --data-urlencode given=João \
20 --data-urlencode identifier=https://www.acmesaude.com.br/integracao/paciente/|507823709 \
21 -d language=pt-BR \
22 --data-urlencode "name=João Silveira" \
23 --data-urlencode organization=Organization/6e6a1b40-1e2a-4f1e-9f0e-2b1c3d4e5f60 \
24 -d phone=5511987654321 \
25 -d phonetic=Silveyra \
26 --data-urlencode telecom=phone|5511987654321

A resposta é sempre um Bundle do tipo searchset, mesmo quando há um único resultado:

Response
1{
2 "resourceType": "Bundle",
3 "type": "searchset",
4 "entry": [
5 {
6 "fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4",
7 "resource": {
8 "identifier": [
9 {
10 "system": "https://www.acmesaude.com.br/integracao/paciente/",
11 "value": "507823709",
12 "use": "usual"
13 }
14 ],
15 "resourceType": "Patient",
16 "active": true,
17 "id": "ba200cfa-dae0-46cf-81a0-008e3f7414b4",
18 "name": [
19 {
20 "family": "Silveira",
21 "given": [
22 "João"
23 ],
24 "use": "official"
25 }
26 ]
27 },
28 "search": {
29 "mode": "match"
30 }
31 }
32 ],
33 "link": [
34 {
35 "relation": "next",
36 "url": "https://landing-zone-api.nilo.services/fhir/resources/Patient?_page_token=Cjj3YopYuf"
37 }
38 ]
39}

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.

Response
1{
2 "resourceType": "Bundle",
3 "type": "searchset",
4 "entry": [],
5 "link": []
6}

Parâmetros de busca suportados

NomeTipoDescriçãoExpressão
identifiertokenIdentificador do paciente, em system|valuePatient.identifier
activetokenSe o cadastro está ativoPatient.active
namestringQualquer parte de qualquer nomePatient.name
familystringParte do sobrenomePatient.name.family
givenstringParte do primeiro nomePatient.name.given
phoneticstringNome por correspondência fonéticaPatient.name
birthdatedateData de nascimentoPatient.birthDate
gendertokenSexo administrativoPatient.gender
telecomtokenQualquer contatoPatient.telecom
phonetokenTelefone de contatoPatient.telecom.where(system='phone')
emailtokenE-mail de contatoPatient.telecom.where(system='email')
addressstringQualquer campo do endereçoPatient.address
address-citystringCidadePatient.address.city
address-statestringEstadoPatient.address.state
address-postalcodestringCEPPatient.address.postalCode
address-countrystringPaísPatient.address.country
address-usetokenFinalidade do endereço — a Nilo grava sempre homePatient.address.use
organizationreferenceUnidade de cuidado, no formato Organization/{id} *Patient.managingOrganization
death-datedateData do óbito(Patient.deceased as dateTime)
deceasedtokenSe está marcado como falecidoPatient.deceased.exists() and Patient.deceased != false
languagetokenIdioma — a Nilo grava sempre pt-BRPatient.communication.language

* 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:

$curl --request GET \
> --url 'https://landing-zone-api.nilo.services/fhir/resources/Patient?identifier=https://www.acmesaude.com.br/integracao/paciente/|507823709' \
> --header 'x-api-key: SUA_API_KEY'

Paginação e recorte por data

Além dos search parameters do Patient, a busca aceita três parâmetros de controle:

NomeDescrição
_lastUpdatedRecorta por data de última alteração, com os prefixos FHIR de comparação (eq, ge, le). Enviado duas vezes, delimita um período
_countQuantos recursos por página
_page_tokenSeleciona a página seguinte

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:

1"link": [
2 {
3 "relation": "next",
4 "url": "https://landing-zone-api.nilo.services/fhir/resources/Patient?_page_token=Cjj3YopYuf"
5 }
6]

Ler por ID

GET
/fhir/resources/Patient/:id
1curl https://landing-zone-api.nilo.services/fhir/resources/Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4 \
2 -H "x-api-key: <apiKey>"

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.entryfullUrl, 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.

Response
1{
2 "fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4",
3 "resource": {
4 "identifier": [
5 {
6 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/hippocrates-api--patient",
7 "value": "48210",
8 "use": "usual"
9 },
10 {
11 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--patient-v2-token",
12 "value": "0f1c2d3e-4a5b-6c7d-8e9f-a0b1c2d3e4f5",
13 "use": "usual"
14 },
15 {
16 "system": "https://www.acmesaude.com.br/integracao/paciente/",
17 "value": "507823709",
18 "use": "usual"
19 },
20 {
21 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--patient-v2",
22 "value": "31502",
23 "use": "usual"
24 }
25 ],
26 "resourceType": "Patient",
27 "active": true,
28 "birthDate": "1974-12-25",
29 "contained": [
30 {
31 "resourceType": "Group",
32 "identifier": [
33 {
34 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/sorting-hat-api--cohort",
35 "value": "904",
36 "use": "usual"
37 },
38 {
39 "system": "https://www.acmesaude.com.br/integracao/grupo/",
40 "value": "diabeticos-tipo-2",
41 "use": "usual"
42 }
43 ],
44 "type": "person",
45 "actual": true,
46 "name": "Diabéticos tipo 2"
47 }
48 ],
49 "communication": [
50 {
51 "language": {
52 "coding": [
53 {
54 "code": "pt-BR",
55 "display": "Portuguese (Brazil)",
56 "system": "urn:ietf:bcp:47"
57 }
58 ]
59 },
60 "preferred": true
61 }
62 ],
63 "extension": [
64 {
65 "url": "http://hl7.org/fhir/StructureDefinition/patient-genderIdentity",
66 "valueCodeableConcept": {
67 "coding": [
68 {
69 "code": "non-disclose",
70 "display": "does not wish to disclose",
71 "system": "http://hl7.org/fhir/gender-identity"
72 }
73 ]
74 }
75 },
76 {
77 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-cohort",
78 "valueIdentifier": {
79 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/sorting-hat-api--cohort",
80 "use": "usual",
81 "value": "904"
82 }
83 },
84 {
85 "extension": [
86 {
87 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-paths-home",
88 "valueUrl": "https://acme.nilocare.app/patients/48210"
89 }
90 ],
91 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-paths"
92 }
93 ],
94 "gender": "male",
95 "id": "ba200cfa-dae0-46cf-81a0-008e3f7414b4",
96 "meta": {
97 "lastUpdated": "2026-08-06T13:04:12.905000Z",
98 "versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
99 },
100 "name": [
101 {
102 "family": "Silveira",
103 "given": [
104 "João"
105 ],
106 "text": "João Silveira",
107 "use": "official"
108 }
109 ]
110 },
111 "search": {
112 "mode": "match"
113 }
114}

Valores aceitos

Sexo

gender segue os códigos administrativos do FHIR, mas só dois sobrevivem à gravação:

EnviadoGravadoNo NiloCare
malemaleMasculino
femalefemaleFeminino
other, unknownother
ausenteother

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:

CódigoNo NiloCare
maleHomem
femaleMulher
transgender-maleHomem Trans
transgender-femaleMulher Trans
otherOutro
non-discloseNão informado

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:

CódigoNo NiloCare
SSolteiro(a)
MCasado(a)
DDivorciado(a)
WViúvo(a)
UNKOutro

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.

Response
1{
2 "issue": [
3 {
4 "code": "structure",
5 "details": {
6 "text": "Invalid CPF: must contain exactly 11 digits with no dots, commas or other characters."
7 },
8 "expression": [
9 "Patient.identifier"
10 ],
11 "severity": "error"
12 }
13 ],
14 "resourceType": "OperationOutcome"
15}

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.

ConfiguraçãoEfeito
Namespaces de identificadorDefine quais system são aceitos para encontrar um paciente já cadastrado, e em que ordem de prioridade
Unidade de cuidado padrãoUsada quando o payload não traz managingOrganization e o paciente ainda não existe
Grupo, boas-vindas e agendamento inicial padrãoPreenchem o que o payload omitir

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:

Response
1{
2 "issue": [
3 {
4 "code": "structure",
5 "details": {
6 "text": "Invalid CPF: must contain exactly 11 digits with no dots, commas or other characters."
7 },
8 "expression": [
9 "Patient.identifier"
10 ],
11 "severity": "error"
12 }
13 ],
14 "resourceType": "OperationOutcome"
15}

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:

POST
/fhir/resources/Patient
1curl -X POST https://landing-zone-api.nilo.services/fhir/resources/Patient \
2 -H "x-api-key: <apiKey>" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "identifier": [
6 {
7 "system": "https://www.acmesaude.com.br/integracao/paciente/",
8 "value": "507823709",
9 "use": "usual"
10 },
11 {
12 "system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
13 "value": "39053344705",
14 "use": "official"
15 }
16 ],
17 "resourceType": "Patient",
18 "gender": "male"
19}'

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:

Response
1{
2 "identifier": [
3 {
4 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/hippocrates-api--patient",
5 "value": "48210",
6 "use": "usual"
7 },
8 {
9 "system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
10 "value": "39053344705",
11 "use": "official"
12 },
13 {
14 "system": "https://www.acmesaude.com.br/integracao/paciente/",
15 "value": "507823709",
16 "use": "usual"
17 },
18 {
19 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--patient-v2",
20 "value": "31502",
21 "use": "usual"
22 }
23 ],
24 "resourceType": "Patient",
25 "active": true,
26 "gender": "male",
27 "id": "ba200cfa-dae0-46cf-81a0-008e3f7414b4",
28 "meta": {
29 "lastUpdated": "2026-08-07T09:22:41.310000Z",
30 "versionId": "MTc4NjA5NDU2MTMxMDAwMDM2Nw"
31 },
32 "name": [
33 {
34 "family": "Silveira",
35 "given": [
36 "João"
37 ],
38 "text": "João Silveira",
39 "use": "official"
40 }
41 ]
42}

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:

POST
/fhir/resources/Patient
1curl -X POST https://landing-zone-api.nilo.services/fhir/resources/Patient \
2 -H "x-api-key: <apiKey>" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "identifier": [
6 {
7 "system": "https://www.acmesaude.com.br/integracao/paciente/",
8 "value": "507823709",
9 "use": "usual"
10 }
11 ],
12 "resourceType": "Patient",
13 "name": [
14 {
15 "family": "Silveira",
16 "given": [
17 "João",
18 "Pedro"
19 ],
20 "text": "João Pedro Silveira",
21 "use": "official"
22 },
23 {
24 "period": {
25 "end": "2026-03-01"
26 },
27 "text": "Joana Silveira",
28 "use": "usual"
29 }
30 ]
31}'

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:

FormaMúltiplos gruposQuando usar
contained com um ou mais GroupsimRecomendada. A única que representa mais de um grupo
extensão …/fhir/resources/Group, com o identificador de um GroupnãoUm grupo só, sem montar o recurso contido
extensão …/StructureDefinition/patient-cohort, com o id Nilo do gruponãoLegada. Mantida por compatibilidade

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:

POST
/fhir/resources/Patient
1curl -X POST https://landing-zone-api.nilo.services/fhir/resources/Patient \
2 -H "x-api-key: <apiKey>" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "identifier": [
6 {
7 "system": "https://www.acmesaude.com.br/integracao/paciente/",
8 "value": "507823709",
9 "use": "usual"
10 }
11 ],
12 "resourceType": "Patient",
13 "contained": [
14 {
15 "resourceType": "Group",
16 "identifier": [
17 {
18 "system": "https://www.acmesaude.com.br/integracao/grupo/",
19 "value": "diabeticos-tipo-2",
20 "use": "usual"
21 }
22 ],
23 "type": "person",
24 "actual": true,
25 "name": "Diabéticos tipo 2"
26 },
27 {
28 "resourceType": "Group",
29 "identifier": [
30 {
31 "system": "https://www.acmesaude.com.br/integracao/grupo/",
32 "value": "hipertensos",
33 "use": "usual"
34 }
35 ],
36 "type": "person",
37 "actual": true,
38 "name": "Hipertensos"
39 }
40 ]
41}'

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:

Response
1{
2 "issue": [
3 {
4 "code": "structure",
5 "details": {
6 "text": "Invalid CPF: must contain exactly 11 digits with no dots, commas or other characters."
7 },
8 "expression": [
9 "Patient.identifier"
10 ],
11 "severity": "error"
12 }
13 ],
14 "resourceType": "OperationOutcome"
15}

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:

Response
1{
2 "issue": [
3 {
4 "code": "structure",
5 "details": {
6 "text": "Invalid CPF: must contain exactly 11 digits with no dots, commas or other characters."
7 },
8 "expression": [
9 "Patient.identifier"
10 ],
11 "severity": "error"
12 }
13 ],
14 "resourceType": "OperationOutcome"
15}

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.