Extensões

Extensões são o mecanismo do FHIR para carregar informação que o recurso padrão não prevê. Elas não alteram a estrutura do recurso: convivem com os campos padrão, e um sistema que não conhece uma extensão continua processando o resto do recurso normalmente.

Na Nilo é por aí que trafega o que é específico da plataforma — o status do paciente, o grupo a que ele pertence, as decisões de onboarding. Algumas são obrigatórias no envio, então esta página não é opcional para quem vai escrever um Patient.

A URL é a chave

Cada extensão é identificada por uma URL, e a comparação é de igualdade exata da string inteira. Não há normalização: nem barra final, nem http por https, nem casamento por sufixo. A URL que você manda é a URL que a Nilo procura, caractere por caractere.

As extensões da Nilo ficam sob:

{host}/fhir/resources/StructureDefinition/

Repare no /resources. E {host} é o host do ambiente que você está chamando — os dois estão em Introdução.

Uma URL de extensão errada não gera erro de URL: a extensão simplesmente não é encontrada. Nas extensões opcionais o valor enviado é ignorado em silêncio — num paciente que já existe a API preserva o valor atual, e num paciente novo aplica o padrão da unidade de cuidado. Nas duas obrigatórias (patient-sendWelcomingMessage e patient-createOnboardingScheduling) o resultado é um 400 dizendo que a extensão é obrigatória, mesmo estando ela ali no payload.

Os dois erros mais comuns são omitir o /resources e usar o host de produção contra homologação.

O tipo do valor também é a chave

O nome do campo de valor — valueBoolean, valueString, valueIdentifier, valueCodeableConcept, valueUrl — faz parte do contrato de cada extensão. A leitura busca exatamente aquele campo: um valueString onde se espera valueBoolean é lido como ausente, com o mesmo desfecho silencioso de uma URL errada. Por isso o catálogo abaixo traz o tipo de cada uma.

Onde aplicar

Uma extensão só é lida no nível em que foi projetada. As de Patient, Coverage, Practitioner e Encounter ficam no extension da raiz do recurso; algumas são compostas e carregam as suas próprias extensões aninhadas, e aí o filho só é encontrado dentro do pai — nunca na raiz. É o caso do practitioner-user-active, que fora de practitioner-user não tem efeito nenhum, e do patient-paths, que a API devolve nas leituras:

1{
2 "extension": [
3 {
4 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-paths",
5 "extension": [
6 {
7 "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-paths-home",
8 "valueUrl": "https://acme.nilocare.app/patients/48210"
9 }
10 ]
11 }
12 ]
13}

Também não convém reescrever a estrutura de uma extensão — trocar o nome do campo de valor, achatar uma composta ou acrescentar elementos à definição produz o mesmo resultado de não a ter enviado.

As extensões da Nilo estão listadas pelo sufixo; o prefixo é {host}/fhir/resources/StructureDefinition/, com o {host} do ambiente que você chama. As duas do hl7.org estão por extenso, porque não ficam sob esse prefixo.

RecursoExtensãoTipoDireçãoO que faz
Patientpatient-sendWelcomingMessagevalueBooleanenvio e respostaDispara ou não a mensagem de boas-vindas após o cadastro. Obrigatória no envio
Patientpatient-createOnboardingSchedulingvalueBooleanenvio e respostaLibera o paciente para o primeiro agendamento logo após o cadastro. Obrigatória no envio
Patientpatient-isLeadvalueBooleanenvio e respostaMarca o cadastro como pré-cadastro: o paciente ainda não aceitou os termos
Patientpatient-statusvalueStringenvio e respostaStatus do paciente, pelo id de um status do seu care provider. Precisa concordar com active
PatientGroup — sem o segmento StructureDefinition/valueIdentifiersó envioGrupo do paciente, pelo identificador de um Group já cadastrado
Patientpatient-cohortvalueIdentifierenvio e respostaGrupo pelo id Nilo. Legada — prefira Group
Patientpatient-religionvalueCodeableConcept (.text)só envioReligião declarada
Patienthttp://hl7.org/fhir/StructureDefinition/patient-genderIdentityvalueCodeableConceptenvio e respostaIdentidade de gênero
Patienthttp://hl7.org/fhir/StructureDefinition/patient-cadavericDonorvalueBooleanenvio e respostaSe o paciente é doador de órgãos
Patientpatient-pathspatient-paths-homeextensionvalueUrlsó respostaAtalho para a ficha do paciente no NiloCare
Coverageinsurance-planvalueIdentifiersó envioProduto da operadora, pelo identificador de um InsurancePlan já cadastrado
Practitionerpractitioner-userextensionsó envioAcesso do profissional ao NiloCare. Composta: carrega -active e -email
Practitionerpractitioner-user-activevalueBooleansó enviotrue concede o acesso, false remove. Só dentro de practitioner-user
Practitionerpractitioner-user-emailvalueStringsó envioE-mail de login. Obrigatória quando o acesso está sendo concedido. Só dentro de practitioner-user
Practitionerpractitioner-organizationvalueIdentifierenvio e respostaUnidade de cuidado do profissional, pelo identificador de uma Organization já cadastrada. Repetível, e só adiciona
Practitionerpractitioner-legacy-typevalueStringsó respostaClassificação interna do profissional, derivada do cadastro
Encounterencounter-admitSourcevalueCodeableConceptenvio e respostaOrigem do atendimento, pelo id de um item do catálogo da implantação. Só em class VR e AMB
Encounterencounter-serviceChannelvalueCodeableConceptenvio e respostaCanal usado no atendimento, pelo id de um item do catálogo. Só em class VR e AMB
Encounterencounter-dischargeDispositionvalueCodeableConceptenvio e respostaDesfecho do atendimento, pelo id de um item do catálogo. Só em class VR e AMB

O que cada uma significa no fluxo do recurso — quais são exigidas, com o que precisam concordar, o que acontece na atualização parcial — está na página do recurso: Paciente, Cobertura, Profissional e Atendimentos.

Nas três extensões do Encounter o coding.system também é load-bearing: precisa ser {host}/fhir/resources/CodeSystem/encounter-admitSource (e equivalentes). Um coding no system errado é lido como ausente, com o mesmo desfecho silencioso de uma URL errada. Elas valem apenas nos atendimentos de class VR e AMB — nos eventos (EMER e IMP) são gravadas e ignoradas.

patient-religion é assimétrica. A escrita aceita a URL sob o prefixo da Nilo, mas a leitura devolve http://hl7.org/fhir/StructureDefinition/patient-religion. Ou seja: reenviar um recurso exatamente como ele veio numa resposta não preserva a religião — reenvie a URL da Nilo.

O grupo tem o mesmo tipo de assimetria: você envia em Group e a resposta traz patient-cohort, com o id Nilo do grupo. As duas descrevem o mesmo vínculo.

As três extensões de acesso do Practitioner são as únicas desta lista que agem fora do recurso: enviá-las cria ou remove um usuário com acesso ao NiloCare. Não as inclua num payload de rotina só porque a plataforma as devolveria — a leitura não as devolve, e mandar practitioner-user-active: false num reenvio remove o acesso de quem já tinha.

Exemplo

O cadastro completo de paciente manda seis extensões de uma vez: as duas obrigatórias, isLead, e as três do hl7.org:

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}'

E a resposta traz as que a Nilo gera, incluindo a composta patient-paths:

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}

Extensões que a Nilo não conhece

Fora as obrigatórias, mande uma extensão só quando ela for relevante para aquele recurso: omitir uma extensão opcional preserva o valor que já está gravado.

Uma extensão cuja URL a Nilo não reconhece não é recusada nem descartada — ela é gravada no recurso e volta nas leituras seguintes, sem nenhum efeito sobre os dados da Nilo. Isso é útil para carregar metadado seu, e é uma armadilha quando a intenção era usar uma extensão da plataforma e a URL saiu errada: o payload volta parecendo correto.