Skip to navigation

Atendimentos

O atendimento é a interação entre o paciente e a equipe com a finalidade de prestar cuidado ou avaliar o estado de saúde. É o registro em torno do qual gira o resto do prontuário — a avaliação clínica, os diagnósticos, as condutas e os documentos emitidos todos apontam para ele.

No FHIR ele é um Encounter, e o campo class decide o que a Nilo cria. Esta página cobre os dois valores que geram um atendimento no prontuário:

class.codeO que a Nilo criaNo NiloCare
VRAtendimento por teleconsultaAtendimentos do paciente
AMBAtendimento presencialAtendimentos do paciente

Os outros dois valores aceitos, EMER e IMP, criam um evento na linha do tempo do paciente em vez de um atendimento, e seguem regras próprias — estão em Pronto atendimento e Hospitalização. Qualquer outro código do vocabulário do FHIR é recusado.

Escrever um atendimento com profissional e sem appointment cria um agendamento na agenda daquele profissional. É o efeito colateral mais forte deste recurso. Antes da primeira carga em volume, leia Agendamento e Efeitos colaterais.

Campos

A coluna No NiloCare traz o rótulo com que o dado aparece para a equipe; 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 na práticaChaves do atendimento. É por aqui que a API decide entre criar e atualizar—
classsimVR para teleconsulta, AMB para presencial—
statussimSituação do atendimento, convertida para um dos três estados da plataforma—
subjectsimO paciente atendido, por um identificador dele já cadastrado—
period.startsimInício do atendimento—
period.endnãoFim do atendimento. Tem de ser maior que period.startFinalizado em
participant[].individualnãoO profissional responsável, por um identificador deleResponsável
participant[].typesim, em cada item de participantPapel do participante, com ao menos um coding com code — só o system não basta. ATND marca o responsável—
appointmentnãoAgendamento já existente a que o atendimento pertence. Um único item—
length.valuenãoDuração em minutos do agendamento criado, quando period.end falta—
extension encounter-admitSourcenãoDe onde veio o atendimentoOrigem do atendimento
extension encounter-serviceChannelnãoPor qual meio o atendimento foi feitoCanal utilizado para o atendimento
extension encounter-dischargeDispositionnãoComo o atendimento terminouDesfecho do atendimento
extension encounter-clinicalNotenãoAnamnese do atendimento, em markdownEntrevista clínica
idnãoSó resposta: o identificador Nilo FHIR do recurso—
metanãoSó resposta: metadados da gravação—

As URLs completas das extensões estão em Extensões — nesta página elas aparecem só pelo nome final.

Campos que a Nilo não usa

O Encounter canônico tem campos que esta integração não lê nem grava: type, serviceType, priority, episodeOfCare, basedOn, reasonCode, reasonReference, account, hospitalization, serviceProvider, partOf, classHistory, statusHistory e participant[].period. Ficam fora da referência de propósito. Como esta referência descreve só o que é suportado, eles não aparecem no schema do recurso. O servidor os aceita, guarda no recurso FHIR e devolve nas leituras seguintes, mas nada no NiloCare passa a exibi-los.

Dois em particular:

  • location não é lido num atendimento do prontuário. O local só existe nos eventos.
  • diagnosis não é lido aqui. Os diagnósticos de um atendimento são escritos pelo recurso Condição.

E dois campos do NiloCare não têm representação FHIR alguma: Criado em é o instante em que a plataforma registrou o atendimento — não é period.start e não é escrito por esta API — e o exame físico não tem campo neste recurso.

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 atendimento com aquele par system + value, ele é atualizado; se não existir, é criado.

POST
/fhir/resources/Encounter
curl -X POST https://landing-zone-api.nilo.services/fhir/resources/Encounter \
-H "x-api-key: <apiKey>" \
-H "Content-Type: application/json" \
-d '{
"class": {
"code": "VR",
"display": "virtual",
"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode"
},
"period": {
"start": "2026-04-16T19:30:00+00:00",
"end": "2026-04-16T20:00:00+00:00"
},
"resourceType": "Encounter",
"status": "finished",
"subject": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709",
"use": "usual"
},
"type": "Patient"
},
"identifier": [
{
"system": "https://www.acmesaude.com.br/integracao/atendimento/",
"value": "55162",
"use": "usual"
}
],
"extension": [
{
"url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/encounter-clinicalNote",
"valueMarkdown": "## Queixa principal\nCefaleia há 3 dias.\n\n## História da doença atual\nDor frontal, pulsátil, pior no fim do dia. Nega febre e vômitos.\n\n## Antecedentes\n- Hipertensão em uso de losartana 50 mg\n- Nega alergias"
}
],
"participant": [
{
"individual": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/profissional/",
"value": "5032932",
"use": "usual"
},
"type": "Practitioner"
},
"type": [
{
"coding": [
{
"code": "ATND",
"display": "attender",
"system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType"
}
],
"text": "attender"
}
]
}
]
}'

A resposta devolve o recurso como ficou gravado:

Response
{
"class": {
"code": "VR",
"display": "virtual",
"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode"
},
"period": {
"start": "2026-04-16T19:30:00+00:00",
"end": "2026-04-16T20:00:00+00:00"
},
"resourceType": "Encounter",
"status": "finished",
"subject": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709",
"use": "usual"
},
"type": "Patient",
"reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4"
},
"id": "7c1d4e08-52ba-4f37-9e6a-3b0d81f5c294",
"meta": {
"lastUpdated": "2026-04-16T20:00:12.441000Z",
"versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
},
"identifier": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--appointment-v3",
"value": "318472",
"use": "usual"
},
{
"system": "https://www.acmesaude.com.br/integracao/atendimento/",
"value": "55162",
"use": "usual"
}
],
"extension": [
{
"url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/encounter-clinicalNote",
"valueMarkdown": "## Queixa principal\nCefaleia há 3 dias.\n\n## História da doença atual\nDor frontal, pulsátil, pior no fim do dia. Nega febre e vômitos.\n\n## Antecedentes\n- Hipertensão em uso de losartana 50 mg\n- Nega alergias"
}
],
"participant": [
{
"individual": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/profissional/",
"value": "5032932",
"use": "usual"
},
"type": "Practitioner",
"reference": "Practitioner/1a9c7f52-64b8-4a3e-8d21-9f0b7c4e6d38"
},
"type": [
{
"coding": [
{
"code": "ATND",
"display": "attender",
"system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType"
}
],
"text": "attender"
}
]
}
]
}

Guarde o id: é por ele que se faz a leitura direta. A resposta traz também o identificador Nilo do atendimento ao lado do seu, no system:

{host}/fhir/resources/NamingSystem/care-api--appointment-v3

Atendimentos sincronizados há mais tempo podem carregar também um identificador no system …/NamingSystem/care-api--appointment, sem o -v3. É o mesmo atendimento: o system antigo é preservado para não partir o histórico. Nos registros novos só o -v3 aparece.

E as consultas antigas do histórico do paciente, que esta API não escreve, chegam com um terceiro system: …/NamingSystem/hippocrates-api--appointment. Veja o aviso em Ler por ID.

O identifier não é exigido pela validação, e é por isso que ele é obrigatório na prática: sem identificador nenhum a API não tem como reconhecer o atendimento, e cada POST cria um atendimento novo. Mande sempre a sua chave.

A atualização substitui, não complementa. Assim como no Coverage e no Practitioner, e diferente do Patient, um campo omitido não preserva o valor atual: omitir period.end volta o atendimento para em andamento, omitir participant apaga o responsável, e omitir as extensões apaga origem, canal e desfecho. Para mudar um campo só, reenvie o atendimento inteiro com o valor novo.

Exceções: o vínculo com o agendamento é preservado — veja Agendamento —, e a entrevista clínica também — veja Entrevista clínica.

Situação do atendimento

status é obrigatório pelo FHIR R4, e os nove valores do padrão são convertidos para os três estados que a plataforma tem:

status enviadoEstado na Nilostatus nas leituras seguintes
planned · arrived · triagedAguardandoplanned
in-progress · onleave · entered-in-error · unknownEm andamentoin-progress
finished · cancelledFinalizadofinished

O status que você enviou continua no recurso FHIR e volta na leitura imediatamente seguinte — inclusive um cancelled, que a plataforma não tem. O valor da plataforma só aparece na próxima vez que o atendimento mudar por lá, e aí substitui o seu. Ou seja: reler o recurso logo depois do POST não confirma o que a Nilo registrou. Use a tabela acima para saber o estado real.

Vale para todo campo que a Nilo não lê, não só para o status: um reenvio em que nada do que a plataforma usa mudou pode não regravar o recurso FHIR, e aí a resposta traz o recurso como ele estava antes. Se você depende de um campo que só existe no seu payload, não conte com ele ter sido atualizado por um reenvio.

Período

period.start é obrigatório:

Resposta 400 — Início do atendimento não informado
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "structure",
"expression": [
"Encounter.period.start"
],
"details": {
"text": "Field period.start is required."
}
}
]
}

period.end é opcional, e quando enviado tem de ser maior que period.start — dois valores iguais são recusados:

Resposta 400 — Fim do atendimento antes do início
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "structure",
"expression": [
"Encounter.period.end"
],
"details": {
"text": "Value of field period.end must be greater than period.start."
}
}
]
}

Profissional responsável

O FHIR permite vários participantes num atendimento; a Nilo registra um: o primeiro item de participant que tem individual e o código ATND em algum coding de type.

{
"type": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType",
"code": "ATND"
}
]
}
],
"individual": { "type": "Practitioner", "identifier": { "…": "…" } }
}

Um item com ATND mas sem individual é pulado, e a escolha segue para o próximo. Os demais itens são aceitos e ignorados, desde que tragam um papel codificado — um participante com PPRF, por exemplo, não muda nada. Se nenhum item traz ATND com individual, o atendimento é criado sem responsável.

Todo item de participant precisa de type com ao menos um coding que tenha code preenchido. Um item sem type, com type só com text, ou com coding só com system recusa a escrita inteira — mesmo que outro item do array traga ATND:

Resposta 400 — Participante sem papel
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "structure",
"expression": [
"Encounter.participant.type"
],
"details": {
"text": "Field participant.type is required. Use code 'ATND' (http://terminology.hl7.org/CodeSystem/v3-ParticipationType) to identify the attending practitioner."
}
}
]
}

Se você não sabe o papel de um participante, não o mande no participant.

O profissional precisa existir — no store FHIR e no cadastro da plataforma. Uma das duas ausências recusa a escrita, com mensagens diferentes:

Resposta 400 — Profissional não encontrado
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "structure",
"expression": [
"Encounter.participant"
],
"details": {
"text": "Practitioner with identifier https://www.acmesaude.com.br/integracao/profissional/|5032932 does not exist or is not active"
}
}
]
}
Resposta 400 — Profissional removido
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "structure",
"expression": [
"Encounter.participant"
],
"details": {
"text": "Practitioner not found."
}
}
]
}

O participant é opcional. Sem ele, o atendimento é criado sem responsável — e sem agendamento:

Requisição — Atendimento presencial sem profissional
{
"resourceType": "Encounter",
"identifier": [
{
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/atendimento/",
"value": "55163"
}
],
"status": "finished",
"class": {
"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
"code": "AMB",
"display": "ambulatory"
},
"subject": {
"type": "Patient",
"identifier": {
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709"
}
},
"period": {
"start": "2026-04-16T14:00:00+00:00",
"end": "2026-04-16T14:40:00+00:00"
}
}

Agendamento

Um atendimento do prontuário pode estar ligado a um agendamento na agenda do profissional, e o campo appointment é como você diz qual:

Requisição — Atendimento em agendamento já existente
{
"resourceType": "Encounter",
"identifier": [
{
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/atendimento/",
"value": "55165"
}
],
"status": "finished",
"class": {
"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
"code": "VR",
"display": "virtual"
},
"subject": {
"type": "Patient",
"identifier": {
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709"
}
},
"participant": [
{
"type": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType",
"code": "ATND",
"display": "attender"
}
],
"text": "attender"
}
],
"individual": {
"type": "Practitioner",
"identifier": {
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/profissional/",
"value": "5032932"
}
}
}
],
"appointment": [
{
"type": "Appointment",
"identifier": {
"use": "usual",
"system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--scheduling-v2",
"value": "90218"
}
}
],
"period": {
"start": "2026-04-16T19:30:00+00:00",
"end": "2026-04-16T20:00:00+00:00"
}
}

Um único item — mais de um é recusado:

Resposta 400 — Mais de um agendamento
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "structure",
"expression": [
"Encounter.appointment"
],
"details": {
"text": "Multiple appointments are not supported."
}
}
]
}

Essa validação só acontece quando há um profissional no participant. Sem profissional, dois appointment passam sem erro e nenhum deles é usado.

Sem appointment e com profissional, um agendamento novo é criado. A API primeiro procura um agendamento daquele profissional para aquele paciente começando exatamente em period.start; não achando, cria um, com conflito de agenda permitido e um resumo gerado automaticamente. O agendamento entra como Agendado se period.start está no futuro e como Realizado se está no passado.

Uma carga histórica de atendimentos com profissional, portanto, popula a agenda de cada profissional com um agendamento por atendimento.

appointment só é considerado quando existe um participant com profissional. Enviar appointment sem profissional não gera erro: a referência é simplesmente ignorada, e o atendimento fica sem agendamento. E numa atualização, o agendamento já vinculado ao atendimento é mantido — o appointment do payload não o troca.

O exemplo acima referencia o agendamento pelo system Nilo (…/NamingSystem/care-api--scheduling-v2), que é o que você tem quando o agendamento nasceu na plataforma. Qualquer identificador do agendamento serve, inclusive um do seu sistema.

Quando o agendamento é criado, a duração dele vem de period.end. Faltando period.end, ela vem de length.value, em minutos:

Requisição — Atendimento sem fim, com duração
{
"resourceType": "Encounter",
"identifier": [
{
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/atendimento/",
"value": "55164"
}
],
"status": "in-progress",
"class": {
"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
"code": "VR",
"display": "virtual"
},
"subject": {
"type": "Patient",
"identifier": {
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709"
}
},
"participant": [
{
"type": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType",
"code": "ATND",
"display": "attender"
}
],
"text": "attender"
}
],
"individual": {
"type": "Practitioner",
"identifier": {
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/profissional/",
"value": "5032932"
}
}
}
],
"period": {
"start": "2026-04-16T19:30:00+00:00"
},
"length": {
"value": 20
}
}

Sem period.end e sem length, o agendamento é criado com 1 minuto de duração. period.end tem prioridade: enviando os dois, length é ignorado.

length é lido sempre em minutos, e a unidade que você declarar é ignorada. {"value": 2, "unit": "h"} produz um agendamento de 2 minutos, não de 2 horas. Converta para minutos antes de enviar.

Origem, canal e desfecho

Três extensões descrevem o contexto do atendimento. Todas carregam um valueCodeableConcept cujo coding.code é o código do catálogo da sua implantação:

Requisição — Com origem, canal e desfecho
{
"resourceType": "Encounter",
"identifier": [
{
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/atendimento/",
"value": "55166"
}
],
"status": "finished",
"class": {
"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
"code": "VR",
"display": "virtual"
},
"subject": {
"type": "Patient",
"identifier": {
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709"
}
},
"period": {
"start": "2026-04-16T19:30:00+00:00",
"end": "2026-04-16T20:00:00+00:00"
},
"extension": [
{
"url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/encounter-admitSource",
"valueCodeableConcept": {
"coding": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/CodeSystem/encounter-admitSource",
"code": "1"
}
]
}
},
{
"url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/encounter-serviceChannel",
"valueCodeableConcept": {
"coding": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/CodeSystem/encounter-serviceChannel",
"code": "3"
}
]
}
},
{
"url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/encounter-dischargeDisposition",
"valueCodeableConcept": {
"coding": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/CodeSystem/encounter-dischargeDisposition",
"code": "7"
}
]
}
}
]
}
ExtensãoNo NiloCare
encounter-admitSourceOrigem do atendimento
encounter-serviceChannelCanal utilizado para o atendimento
encounter-dischargeDispositionDesfecho do atendimento

O coding.system precisa ser o do catálogo correspondente — {host}/fhir/resources/CodeSystem/encounter-admitSource e equivalentes. Um coding em outro system é ignorado, e a extensão não tem efeito. Aqui, diferente do class, o system é conferido.

Havendo mais de uma extensão com a mesma URL no payload, vale a primeira — exceto a entrevista clínica, que não pode se repetir. E na leitura a Nilo devolve o display e o text preenchidos com o nome do item do catálogo, que é o que aparece na tela — no envio esses dois campos não são necessários.

Os códigos de origem, canal e desfecho são configurados por implantação, e não há catálogo publicado nesses system: GET /fhir/resources/CodeSystem/encounter-admitSource responde 404. Peça a lista ao Suporte, ou leia um atendimento já registrado pela plataforma e aproveite os códigos que vierem nas extensões.

Entrevista clínica

A anamnese do atendimento entra pela extensão encounter-clinicalNote, com o texto em valueMarkdown. É o campo Entrevista clínica do atendimento no NiloCare, e o mesmo texto que a leitura de Avaliação clínica devolve em description.

Requisição — Com entrevista clínica
{
"resourceType": "Encounter",
"identifier": [
{
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/atendimento/",
"value": "55167"
}
],
"status": "finished",
"class": {
"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
"code": "VR",
"display": "virtual"
},
"subject": {
"type": "Patient",
"identifier": {
"use": "usual",
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709"
}
},
"period": {
"start": "2026-04-16T19:30:00+00:00",
"end": "2026-04-16T20:00:00+00:00"
},
"extension": [
{
"url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/encounter-clinicalNote",
"valueMarkdown": "## Queixa principal\nCefaleia há 3 dias.\n\n## História da doença atual\nDor frontal, pulsátil, pior no fim do dia. Nega febre e vômitos.\n\n## Antecedentes\n- Hipertensão em uso de losartana 50 mg\n- Nega alergias"
}
]
}

As regras:

  • Com a extensão, a entrevista clínica do atendimento é criada ou substituída pelo texto enviado.
  • Sem a extensão, a entrevista clínica já gravada é mantida. É a exceção à regra de que a atualização substitui o atendimento inteiro.
  • O texto vai obrigatoriamente em valueMarkdown. Uma extensão sem ele — vazia, só com espaços e quebras de linha, ou com o texto em valueString — é recusada.
  • A extensão aparece uma vez só. Diferente de origem, canal e desfecho, em que vale a primeira, repeti-la é recusado: a API não escolhe qual das anamneses gravar.
  • A API grava o texto como ele veio: não valida nem converte o markdown.
  • Na leitura, o Encounter traz a extensão sempre que o atendimento tem entrevista clínica.
  • Como as demais extensões do atendimento, ela só é lida em class VR e AMB.
Resposta 400 — Entrevista clínica sem texto
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "structure",
"expression": [
"Encounter.extension"
],
"details": {
"text": "Extension encounter-clinicalNote requires a non-empty valueMarkdown."
}
}
]
}
Resposta 400 — Entrevista clínica repetida
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "structure",
"expression": [
"Encounter.extension"
],
"details": {
"text": "Extension encounter-clinicalNote must not be repeated."
}
}
]
}

O NiloCare renderiza um subconjunto do markdown:

MarkdownResultadoNo NiloCare
Linha em branco entre blocosNovo parágrafo—
\n simplesQuebra de linha dentro do parágrafo—
# , ## , ### Título, subtítulo e subtítulo menorTítulo · Subtítulo · Subtítulo menor
- item (também * e +)Lista com marcadoresLista
1. itemLista numeradaLista numerada
- [ ] item / - [x] itemLista de tarefas com caixa de seleção, aninhávelLista de tarefas
> textoCitaçãoCitação
--- numa linha sozinhaLinha horizontalLinha horizontal
[texto](https://...)LinkLink

O resto aparece como texto literal, com os caracteres exatamente como foram enviados:

  • negrito e itálico: **x**, *x*, _x_
  • tachado: ~~x~~
  • código: `x`, blocos cercados por ``` e linhas indentadas com 4 espaços
  • imagem: ![alt](src)
  • título sublinhado, com uma linha de === ou --- abaixo do texto — só o # vale como título
  • HTML: <b>, <br /> e qualquer outra tag

Evite também tabelas (| a | b |), títulos de #### em diante e URLs soltas, fora de [texto](url): o NiloCare não tem formatação para eles.

Negrito e itálico não são renderizados. Quem já gera markdown tende a escrever **Queixa principal:**, e o profissional vê os asteriscos. Use títulos (##) e listas para dar estrutura ao texto.

E não há como apagar a entrevista clínica pela API: omitir a extensão preserva o texto gravado, e um valueMarkdown vazio ou só com espaços é recusado.

A formatação aparece só no registro de atendimento atual do NiloCare. Na versão anterior do registro e no detalhe do atendimento na linha do tempo do paciente, o texto aparece sem formatação, com os caracteres de markdown à vista. Escreva de modo que ele continue legível como texto puro.

Paciente

subject é obrigatório, e o paciente tem de existir — no store FHIR e no cadastro da plataforma. As duas ausências têm mensagens diferentes:

Resposta 400 — Paciente não encontrado
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "structure",
"expression": [
"Encounter.subject"
],
"details": {
"text": "Patient with identifier https://www.acmesaude.com.br/integracao/paciente/|507823709 does not exist or is not active"
}
}
]
}
Resposta 400 — Paciente removido
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "structure",
"expression": [
"Encounter.subject"
],
"details": {
"text": "Patient not found."
}
}
]
}

Um atendimento não cria paciente. Cadastre o Paciente primeiro.

Buscar

GET
/fhir/resources/Encounter
curl -G https://landing-zone-api.nilo.services/fhir/resources/Encounter \
-H "x-api-key: <apiKey>" \
-d _lastUpdated=eq2013-01-14 \
--data-urlencode class=http://terminology.hl7.org/CodeSystem/v3-ActCode|VR \
-d date=ge2026-04-01 \
--data-urlencode diagnosis=Condition/c61b5f58-32b0-477b-b75a-54e306952082 \
--data-urlencode identifier=https://www.acmesaude.com.br/integracao/atendimento/|55162 \
--data-urlencode participant=Practitioner/1a9c7f52-64b8-4a3e-8d21-9f0b7c4e6d38 \
--data-urlencode participant-type=http://terminology.hl7.org/CodeSystem/v3-ParticipationType|ATND \
--data-urlencode patient=Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4 \
--data-urlencode patient:identifier=https://www.acmesaude.com.br/integracao/paciente/|507823709 \
--data-urlencode practitioner=Practitioner/1a9c7f52-64b8-4a3e-8d21-9f0b7c4e6d38 \
-d status=finished \
--data-urlencode subject=Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4

A busca é a mesma para atendimentos e eventos, porque os quatro tipos são o mesmo recurso FHIR. Para trazer só os atendimentos do prontuário, filtre por class:

curl --request GET \
--url 'https://landing-zone-api.nilo.services/fhir/resources/Encounter?patient:identifier=https://www.acmesaude.com.br/integracao/paciente/|507823709&class=VR,AMB' \
--header 'x-api-key: SUA_API_KEY'

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

Response
{
"resourceType": "Bundle",
"type": "searchset",
"entry": [
{
"fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/Encounter/7c1d4e08-52ba-4f37-9e6a-3b0d81f5c294",
"resource": {
"class": {
"code": "VR",
"display": "virtual",
"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode"
},
"period": {
"start": "2026-04-16T19:30:00+00:00",
"end": "2026-04-16T20:00:00+00:00"
},
"resourceType": "Encounter",
"status": "finished",
"subject": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709",
"use": "usual"
},
"type": "Patient",
"reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4"
},
"id": "7c1d4e08-52ba-4f37-9e6a-3b0d81f5c294",
"identifier": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--appointment-v3",
"value": "318472",
"use": "usual"
},
{
"system": "https://www.acmesaude.com.br/integracao/atendimento/",
"value": "55162",
"use": "usual"
}
],
"extension": [
{
"url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/encounter-serviceChannel",
"valueCodeableConcept": {
"coding": [
{
"code": "3",
"display": "Vídeo",
"system": "https://landing-zone-api.nilo.services/fhir/resources/CodeSystem/encounter-serviceChannel"
}
],
"text": "Vídeo"
}
}
],
"participant": [
{
"individual": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/profissional/",
"value": "5032932",
"use": "usual"
},
"type": "Practitioner",
"reference": "Practitioner/1a9c7f52-64b8-4a3e-8d21-9f0b7c4e6d38"
},
"type": [
{
"coding": [
{
"code": "ATND",
"display": "attender",
"system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType"
}
],
"text": "attender"
}
]
}
]
},
"search": {
"mode": "match"
}
}
],
"link": []
}

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
{
"resourceType": "Bundle",
"type": "searchset",
"entry": [],
"link": []
}

Parâmetros de busca suportados

NomeTipoDescriçãoExpressão
identifiertokenIdentificador do atendimento, em system|valueEncounter.identifier
patient:identifierreferencePaciente atendido, pelo identificador deleEncounter.subject.identifier
patientreferencePaciente atendido, pelo id Nilo FHIREncounter.subject
subjectreferenceO mesmo campo que patient, e aceita o mesmo :identifierEncounter.subject
classtokenTipo do atendimento — VR ou AMB aqui, EMER e IMP nos eventosEncounter.class
statustokenSituação — na prática, planned, in-progress ou finishedEncounter.status
datedatePeríodo do atendimento, com os prefixos eq, ge, leEncounter.period
practitionerreferenceProfissional responsável. Aceita :identifierEncounter.participant.individual
participantreferenceO mesmo campo que practitionerEncounter.participant.individual
participant-typetokenPapel do participante — ATND nos atendimentos do prontuárioEncounter.participant.type

Qual identificador do paciente o subject carrega depende da sua implantação. Na configuração que usa identificadores externos nas referências, é o identificador do seu sistema — e o filtro acima funciona como está. Sem ela, o subject traz o identificador Nilo do paciente (…/NamingSystem/hippocrates-api--patient), e é esse system que você tem de usar no filtro. Confira numa resposta de leitura qual dos dois está lá antes de montar a busca em volume. O mesmo vale para practitioner.

Vários parâmetros canônicos do Encounter existem e não encontram nada aqui, porque a Nilo não preenche o campo correspondente: type, service-provider, episode-of-care, based-on, part-of, reason-code, reason-reference, account e special-arrangement.

appointment e length só encontram os atendimentos em que você enviou aqueles campos — a plataforma não os produz por conta própria. E location e diagnosis só encontram eventos.

Ler por ID

GET
/fhir/resources/Encounter/:id
curl https://landing-zone-api.nilo.services/fhir/resources/Encounter/id \
-H "x-api-key: <apiKey>"

A leitura por ID responde 404 quando o id não existe.

Diferente da busca, esta leitura não devolve um Bundle — mas também não devolve o recurso nu. A resposta é um envelope com fullUrl, search e resource, e o atendimento está em resource. Ler status ou identifier na raiz da resposta não encontra nada.

Response
{
"fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/Encounter/7c1d4e08-52ba-4f37-9e6a-3b0d81f5c294",
"resource": {
"class": {
"code": "VR",
"display": "virtual",
"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode"
},
"period": {
"start": "2026-04-16T19:30:00+00:00",
"end": "2026-04-16T20:00:00+00:00"
},
"resourceType": "Encounter",
"status": "finished",
"subject": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente/",
"value": "507823709",
"use": "usual"
},
"type": "Patient",
"reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4"
},
"id": "7c1d4e08-52ba-4f37-9e6a-3b0d81f5c294",
"meta": {
"lastUpdated": "2026-04-16T20:00:12.441000Z",
"versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
},
"identifier": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--appointment-v3",
"value": "318472",
"use": "usual"
},
{
"system": "https://www.acmesaude.com.br/integracao/atendimento/",
"value": "55162",
"use": "usual"
}
],
"extension": [
{
"url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/encounter-admitSource",
"valueCodeableConcept": {
"coding": [
{
"code": "1",
"display": "Busca ativa",
"system": "https://landing-zone-api.nilo.services/fhir/resources/CodeSystem/encounter-admitSource"
}
],
"text": "Busca ativa"
}
},
{
"url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/encounter-serviceChannel",
"valueCodeableConcept": {
"coding": [
{
"code": "3",
"display": "Vídeo",
"system": "https://landing-zone-api.nilo.services/fhir/resources/CodeSystem/encounter-serviceChannel"
}
],
"text": "Vídeo"
}
},
{
"url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/encounter-dischargeDisposition",
"valueCodeableConcept": {
"coding": [
{
"code": "7",
"display": "Alta",
"system": "https://landing-zone-api.nilo.services/fhir/resources/CodeSystem/encounter-dischargeDisposition"
}
],
"text": "Alta"
}
},
{
"url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/encounter-clinicalNote",
"valueMarkdown": "## Queixa principal\nCefaleia há 3 dias.\n\n## História da doença atual\nDor frontal, pulsátil, pior no fim do dia. Nega febre e vômitos.\n\n## Antecedentes\n- Hipertensão em uso de losartana 50 mg\n- Nega alergias"
}
],
"participant": [
{
"individual": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/profissional/",
"value": "5032932",
"use": "usual"
},
"type": "Practitioner",
"reference": "Practitioner/1a9c7f52-64b8-4a3e-8d21-9f0b7c4e6d38"
},
"type": [
{
"coding": [
{
"code": "ATND",
"display": "attender",
"system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType"
}
],
"text": "attender"
}
]
}
]
},
"search": {
"mode": "match"
}
}

Nem tudo o que você lê foi escrito por esta API. Atendimentos registrados pela equipe no NiloCare aparecem aqui do mesmo jeito — e consultas mais antigas do histórico do paciente vêm com class AMB, status finished e um participant que traz apenas o papel, com o código CBO da especialidade em type, sem individual. É a especialidade que atendeu, não a pessoa.

Valores aceitos

Classes

class.code usa o vocabulário v3-ActEncounterCode. Os dois códigos desta página:

CódigodisplayO que cria
VRvirtualAtendimento por teleconsulta
AMBambulatoryAtendimento presencial

O system esperado é http://terminology.hl7.org/CodeSystem/v3-ActCode. Os códigos que criam evento em vez de atendimento — EMER e IMP — estão nas páginas dos eventos. Qualquer outro código do vocabulário (HH, SS, OBSENC, PRENC, FLD, ACUTE, NONAC) é recusado:

Resposta 400 — Classe de atendimento não suportada
{
"errors": "Encounter class SS is not supported"
}

Situações

status aceita os nove códigos do FHIR R4 no envio. Nas leituras, só três aparecem: planned, in-progress e finished. A conversão está em Situação do atendimento.

Papel do participante

participant[].type usa o vocabulário v3-ParticipationType. O único código com significado aqui é ATND (attender), e é o que a Nilo devolve nas leituras.

Catálogos de origem, canal e desfecho

Não são vocabulários desta API: são catálogos que a sua implantação mantém, e o code é o id do item no catálogo. Não há catálogo publicado nesses system — veja o aviso em Origem, canal e desfecho.

Efeitos colaterais

Um atendimento com profissional e sem appointment cria um agendamento na agenda daquele profissional, com conflito de agenda permitido.

Reenviar um atendimento cujo identificador aponta para um registro que não existe mais na Nilo faz a API remover o recurso FHIR órfão e criar um atendimento novo em seguida. É a forma de não deixar dois recursos com o mesmo identificador, mas o id Nilo FHIR muda: o id que você tinha guardado deixa de resolver.

Este endpoint não remove atendimentos: a escrita nunca responde 204. A remoção acontece do lado da plataforma e é propagada para o store FHIR pela sincronização.

Erros

Recusa é 400, e o corpo é um OperationOutcome: issue[].expression aponta o campo culpado e issue[].details.text explica o motivo. O outro código que este endpoint devolve é 429, quando o limite de escrita do tipo de recurso é atingido — nesse caso, aguarde e repita.

Há uma exceção de forma. O class.code não suportado é recusado antes de o atendimento chegar à camada FHIR, e volta com só um campo errors com a mensagem, sem issue, sem code e sem expression:

Resposta 400 — Classe de atendimento não suportada
{
"errors": "Encounter class SS is not supported"
}

O que a integração não cobre

A entrevista clínica entra pelo Encounter — veja Entrevista clínica —, mas o exame físico e os pontos de atenção não são campos dele: estão só na leitura de Avaliação clínica. As condutas e orientações estão em Conduta, os diagnósticos do atendimento em Condição e os medicamentos em Medicamento. Os documentos emitidos no atendimento — prescrição, solicitação de exame e encaminhamento — também têm recursos próprios. A diretriz aplicada ao paciente não é alcançável a partir do atendimento.

Também não há como, por esta API: registrar mais de um profissional num atendimento, ou informar o local de um atendimento do prontuário — local só existe nos eventos.