Plano de cuidado

Uma diretriz é o desenho do cuidado: a sequência de consultas, tarefas, questionários e mensagens que a equipe deve executar para acompanhar um paciente. O plano de cuidado é essa diretriz aplicada a um paciente — o par que liga uma pessoa a um roteiro de acompanhamento.

No FHIR, a diretriz é um PlanDefinition e a aplicação dela é um CarePlan. Esta página cobre a segunda metade: como colocar um paciente numa diretriz, como acompanhar o que foi gerado para ele e como encerrar o acompanhamento.

O conteúdo da diretriz — as consultas, tarefas e questionários que ela gera — é montado pela equipe no NiloCare, não por esta API. O que você faz aqui é aplicá-la, e para isso precisa da URL da diretriz, que a busca de diretrizes devolve. O cabeçalho da diretriz (nome, descrição e tipo) esse sim é gravável — veja Diretriz.

Linha de cuidado e protocolo

A plataforma organiza as diretrizes em dois tipos:

TipoComo a equipe o usaExemplo
Linha de cuidadoAcompanhamento contínuo de uma condição crônicaDiabetes, hipertensão
ProtocoloUm roteiro com começo, meio e fim, de tarefas sequenciaisAcompanhamento pós-operatório

O tipo vem na leitura em category[0].text, com os códigos care_line e protocol. Não é algo que você escolha no payload deste recurso: ele é propriedade da diretriz — veja Diretriz.

Antes de aplicar

A aplicação de uma diretriz não depende só do plano — depende de como o paciente está cadastrado. Dois requisitos, os dois verificados pela plataforma no momento da aplicação:

  1. O paciente tem equipe de cuidado. Um paciente sem equipe é recusado.
  2. A equipe cobre as especialidades que a diretriz exige. Precisa haver ao menos um profissional para cada especialidade pedida — pode ser o mesmo profissional cobrindo mais de uma. Faltando alguma, a aplicação é bloqueada.

Os dois erros vêm da plataforma, não da validação do recurso: saem com expression igual a CarePlan.? e com o motivo em texto (patient_without_care_team, todo_without_responsible). CarePlan.? não é FHIRPath válido — não tente resolvê-lo automaticamente para apontar o campo culpado.

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.

CampoObrigatórioO que significaNo NiloCare
resourceTypesimConstante CarePlan
statussimNa escrita, escolhe o que acontece — veja Aplicar. Na leitura, a situação do planoselo Encerrada na diretriz
intentsimExigido pelo FHIR R4 e não lido pela Nilo. Envie order
subjectsimO paciente, por um identificador dele. type tem de ser PatientPaciente
instantiatesCanonicalsimA diretriz a aplicar, pela URL do PlanDefinition. Só o primeiro item é lidoDiretriz
identifiernão pela validação, sim na práticaSuas chaves do plano. É por aqui que a API reconhece um plano já existente
titlenãoSó resposta: nome da diretrizDiretriz
descriptionnãoSó resposta: descrição da diretriz
categorynãoSó resposta: care_line ou protocol, em texto livreLinha de cuidado / Protocolo
periodnãoSó resposta: início e fim da aplicação ao pacienteInício da diretriz
creatednãoSó resposta: data de criação do plano, sem hora
activitynãoSó resposta: os itens gerados pela diretrizitens do plano
notenãoSó resposta, e só quando a alocação em massa falhou: o motivo da falha
id · metanãoSó resposta: identificador Nilo FHIR e metadados da gravação

Campos que a Nilo não usa

A CarePlan canônica traz muito mais do que esta integração lê: basedOn, replaces, partOf, encounter, careTeam, addresses, goal, contributor, supportingInfo, instantiatesUri, partOf e contained. Nenhum deles é lido, e por isso nenhum aparece na referência do recurso.

author é a exceção que morde. Ele não grava nada — nem o profissional que aplicou a diretriz — mas, ao contrário dos outros, é validado. O type é conferido em toda escrita: qualquer coisa diferente de Practitioner recusa a chamada. E, nas chamadas que criam ou recriam o plano, o identificador também é resolvido: um profissional inexistente ou inativo recusa a escrita inteira. Num encerramento ou cancelamento o identificador nem chega a ser consultado.

Como não há benefício algum em enviá-lo, não envie. Ele não aparece na referência do recurso justamente por isso; as linhas de erro abaixo existem para quem já o manda hoje.

Encontrar a diretriz

instantiatesCanonical é a URL da diretriz. Você a obtém listando as diretrizes disponíveis — veja Diretriz:

GET
/fhir/resources/PlanDefinition
1curl -G https://landing-zone-api.nilo.services/fhir/resources/PlanDefinition \
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 --data-urlencode identifier=https://www.acmesaude.com.br/integracao/diretriz/|DM2 \
7 -d name=Acompanhamento \
8 -d status=active \
9 --data-urlencode type=http://terminology.hl7.org/CodeSystem/plan-definition-type|order-set \
10 --data-urlencode url=https://www.acmesaude.com.br/diretrizes/diabetes-tipo-2

A URL a enviar é {host}/fhir/resources/PlanDefinition/{id}, com o id do recurso encontrado — ou a url canônica da diretriz, quando ela tiver uma.

A resolução aceita duas formas: a API tenta primeiro o último segmento da URL como id do recurso e, não achando, procura uma diretriz cujo campo url seja exatamente o que você enviou. Nos dois caminhos a diretriz precisa estar com status: active.

A URL embute o host do ambiente. Um payload com a URL de produção enviado para o ambiente de homologação é recusado antes de qualquer validação de negócio, com a mensagem Resource has identifier from a Nilo environment that is not the current environment. Ao promover uma integração entre ambientes, troque o host de todos os instantiatesCanonical.

Aplicar a diretriz

Não há endpoint separado para criar e atualizar: o mesmo POST faz os dois, e o status enviado é o que decide o que acontece.

Os dois modos de aplicação

statusO que acontece
draftFila de alocação. O paciente entra na fila e a plataforma avalia a capacidade da equipe antes de aplicar. Nesta chamada nada é criado na plataforma — só o recurso FHIR
activeAplicação imediata. O plano é criado durante a requisição, sem passar pela fila
POST
/fhir/resources/CarePlan
1curl -X POST https://landing-zone-api.nilo.services/fhir/resources/CarePlan \
2 -H "x-api-key: <apiKey>" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "instantiatesCanonical": [
6 "https://landing-zone-api.nilo.services/fhir/resources/PlanDefinition/aba72582-f9fb-49ea-b316-73b8dba2a4d7"
7 ],
8 "intent": "order",
9 "resourceType": "CarePlan",
10 "status": "active",
11 "subject": {
12 "identifier": {
13 "system": "https://www.acmesaude.com.br/integracao/paciente/",
14 "value": "507823709",
15 "use": "usual"
16 },
17 "type": "Patient"
18 },
19 "identifier": [
20 {
21 "system": "https://www.acmesaude.com.br/integracao/plano-de-cuidado/",
22 "value": "349223",
23 "use": "usual"
24 }
25 ]
26}'

A resposta devolve o recurso como ficou gravado, sem envelope:

Response
1{
2 "instantiatesCanonical": [
3 "https://landing-zone-api.nilo.services/fhir/resources/PlanDefinition/aba72582-f9fb-49ea-b316-73b8dba2a4d7"
4 ],
5 "intent": "order",
6 "resourceType": "CarePlan",
7 "status": "active",
8 "subject": {
9 "identifier": {
10 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/hippocrates-api--patient",
11 "value": "1013441",
12 "use": "usual"
13 },
14 "type": "Patient",
15 "reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4"
16 },
17 "category": [
18 {
19 "text": "care_line"
20 }
21 ],
22 "created": "2026-04-16",
23 "description": "Acompanhamento longitudinal de pacientes com diabetes tipo 2.",
24 "id": "3f21a0d5-9c74-4b18-a6e2-51d8c93f7ab0",
25 "identifier": [
26 {
27 "system": "https://www.acmesaude.com.br/integracao/plano-de-cuidado/",
28 "value": "349223",
29 "use": "usual"
30 },
31 {
32 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/hippocrates-api--patient-care-line",
33 "value": "184532",
34 "use": "usual"
35 }
36 ],
37 "meta": {
38 "lastUpdated": "2026-04-16T20:05:03.118000Z",
39 "versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
40 },
41 "period": {
42 "start": "2026-04-16"
43 },
44 "title": "Diabetes tipo 2"
45}

Guarde o id: é por ele que se faz a leitura direta. Ao lado do seu identifier, a resposta traz o identificador Nilo do plano, no system …/NamingSystem/hippocrates-api--patient-care-line.

A aplicação imediata confirma a criação do plano, não a geração dos itens. As tarefas, os agendamentos, os questionários e as mensagens são gerados depois, de forma assíncrona, e a geração pode levar alguns minutos.

O status da resposta repete o que você enviou, não o estado derivado do plano na plataforma. Uma aplicação imediata responde active mesmo enquanto os itens ainda estão sendo gerados — nesse intervalo o plano vale como pendente do outro lado, e uma leitura posterior pode trazê-lo como on-hold, sem activity. O sinal de que a geração terminou é a activity aparecer numa leitura, não o status da resposta ao POST.

Um plano criado com status: draft não tem identificador Nilo: nada foi criado na plataforma ainda. O recurso FHIR é o seu próprio payload, sem title, sem category, sem period e sem activity. Não conte com esses campos antes de a alocação acontecer — e veja o que isso implica para cancelar um plano ainda na fila.

subject.identifier volta trocado. Você envia o identificador do seu sistema, e a resposta traz o identificador Nilo do paciente (…/NamingSystem/hippocrates-api--patient). Não é perda de dado: é a referência que a plataforma usa internamente. Leituras posteriores do mesmo plano podem trazer o seu identificador de volta, dependendo da configuração da sua implantação.

Como a API reconhece o plano

Duas chaves, nesta ordem.

Com identifier. A API procura um plano com aquele par system + value, em qualquer estado. Achando, a chamada é uma atualização daquele plano, e valem as regras de transição de estado.

Sem identifier, ou com um identifier que não casa com nada. A API procura pelo par subject + instantiatesCanonical, entre os planos nos estados draft, active, on-hold e entered-in-error — planos já encerrados ou cancelados não entram nessa busca.

O que acontece então depende de qual das duas situações é a sua:

Você enviouNão há plano para o parHá plano draft ou entered-in-errorHá plano active ou on-hold
identifier novo, status: activeCria o planoAplica agora o plano que estava na filaO seu identifier é anexado ao plano existente, e ele volta como está
identifier novo, status: draftEnfileiraidentifier anexado; nada mudaidentifier anexado; nada muda
identifier novo, outro statusRecusado: CarePlan can only be created with status draft or activeidemidem
sem identifierCria, se o status for draft ou active; senão recusadoAtualização — menos com draft ou active¹Atualização — menos com draft ou active¹

¹ Um plano já existente não aceita draft nem active de novo: a chamada é recusada com CarePlan can't be updated to status …. A única exceção é o plano em entered-in-error.

A célula que costuma surpreender é a da última coluna: enviar um identifier novo para um paciente que já está naquela diretriz não cria plano nenhum e não devolve erro. A resposta é 200 com o plano que já existia, agora carregando também a sua chave. Se o seu integrador conta chamadas bem-sucedidas como planos criados, ele vai contar errado. Confira o identificador Nilo da resposta antes de concluir que aplicou a diretriz — e note que o status da resposta não ajuda nessa distinção, porque ele repete o que você enviou.

Um paciente tem, no máximo, um plano não terminal por diretriz. Havendo mais de um no store — estado inconsistente, que não deveria acontecer — a escrita falha com IntegrityError: has more than one Care Plan for Patient and PlanDefinition, e o caso é de chamado no Suporte.

Estados e transições

Na leitura, o status do plano vem derivado da situação dele na plataforma:

Situação na plataformastatus na leitura
Pendente, na fila ou em geração de itenson-hold
Em execuçãoactive
Concluídocompleted
Cancelado, removido ou com falharevoked
Sem situação registradaunknown

Na escrita, o status é uma instrução, e nem toda transição é permitida:

DePara draft / activePara on-holdPara completedPara revoked / entered-in-error
draftrecusadorecusado¹recusado¹recusado¹
active · on-holdrecusadopermitidopermitidopermitido
entered-in-errorpermitidopermitido²permitido²permitido²
revoked · completedrecusadorecusadorecusadorecusado

¹ Um plano ainda em draft não tem registro na plataforma para atualizar. A tentativa falha com CarePlan with nilo identifier does not exist.

² Com a mesma ressalva: o plano entered-in-error típico é o que falhou na alocação em massa, e ele nasceu em draft — então não tem registro na plataforma, e essas três transições falham pelo mesmo motivo. O que funciona nele é reenviá-lo como active ou como draft.

revoked e completed são terminais. Um plano nesses estados não aceita mais nenhuma atualização: qualquer POST que o alcance pelo identifier é recusado com CarePlan with status … can't be updated.

Para aplicar a mesma diretriz de novo ao mesmo paciente, envie um identifier novo. Isso é deliberado: cada aplicação é uma entrada distinta no histórico do paciente naquela diretriz, com a data em que entrou e a data em que saiu.

entered-in-error é o único estado não terminal do qual se volta. Um plano que falhou na alocação em massa pode ser reenviado com status: active, e aí um plano novo é criado — ou com status: draft, e ele volta para a fila.

Encerrar ou cancelar

Para tirar um paciente de uma diretriz, reenvie o plano trocando só o status:

  • completed — o acompanhamento chegou ao fim como previsto.
  • revoked — a aplicação foi indevida e está sendo desfeita.
POST
/fhir/resources/CarePlan
1curl -X POST https://landing-zone-api.nilo.services/fhir/resources/CarePlan \
2 -H "x-api-key: <apiKey>" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "instantiatesCanonical": [
6 "https://landing-zone-api.nilo.services/fhir/resources/PlanDefinition/aba72582-f9fb-49ea-b316-73b8dba2a4d7"
7 ],
8 "intent": "order",
9 "resourceType": "CarePlan",
10 "status": "revoked",
11 "subject": {
12 "identifier": {
13 "system": "https://www.acmesaude.com.br/integracao/paciente/",
14 "value": "507823709",
15 "use": "usual"
16 },
17 "type": "Patient"
18 },
19 "identifier": [
20 {
21 "system": "https://www.acmesaude.com.br/integracao/plano-de-cuidado/",
22 "value": "349223",
23 "use": "usual"
24 }
25 ]
26}'

Os dois tiram o paciente do acompanhamento. A diferença é de intenção, e ela fica no histórico do paciente.

entered-in-error tem, na plataforma, o mesmo efeito de revoked. A distinção existe no recurso FHIR, não no registro.

Não é preciso mandar o identifier para encerrar: sem ele, o plano é localizado pelo par paciente + diretriz.

POST
/fhir/resources/CarePlan
1curl -X POST https://landing-zone-api.nilo.services/fhir/resources/CarePlan \
2 -H "x-api-key: <apiKey>" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "instantiatesCanonical": [
6 "https://landing-zone-api.nilo.services/fhir/resources/PlanDefinition/aba72582-f9fb-49ea-b316-73b8dba2a4d7"
7 ],
8 "intent": "order",
9 "resourceType": "CarePlan",
10 "status": "revoked",
11 "subject": {
12 "identifier": {
13 "system": "https://www.acmesaude.com.br/integracao/paciente/",
14 "value": "507823709",
15 "use": "usual"
16 },
17 "type": "Patient"
18 }
19}'

Um plano ainda em draft não pode ser cancelado. Ele existe só como recurso FHIR, e o cancelamento precisa de um registro na plataforma para atualizar — a chamada falha com CarePlan with nilo identifier does not exist, e o paciente continua na fila.

Duas saídas: esperar a alocação acontecer e cancelar depois, ou aplicar o plano agora enviando um identifier novo com status: active — é esse caminho, e não o reenvio sem identifier, que promove um plano da fila. Aplicado, ele passa a aceitar o cancelamento.

Essa mensagem não é exclusiva do draft: ela aparece sempre que o recurso alcançado não carrega o identificador Nilo do plano. O plano na fila é o caso comum porque nunca teve um — mas um recurso active que tenha perdido o identificador falha igual.

Itens do plano

activity é o que a diretriz gerou para aquele paciente. É só leitura: os itens não são criados nem alterados por este recurso. Cada item vem de uma de duas formas.

Com reference e progress, quando o item já tem recurso próprio no store:

O item éreference.typeValores de progress[0].text
Consulta agendadaAppointmentnot-started · scheduled · cancelled · completed · unknown
Tarefa da equipeTaskrequested · in-progress · completed
Questionário do pacienteTaskrequested · completed
Mensagem programadaCommunicationRequestrequested · completed

Com detail, quando a diretriz prevê uma consulta que ainda não virou agendamento: detail.kind é sempre Appointment, detail.description traz a especialidade prevista, detail.scheduledPeriod a janela em que ela deveria acontecer e detail.status o andamento, com os mesmos valores da consulta agendada.

A janela de scheduledPeriod é fixa em sete dias: o fim é sempre sete dias depois do início. Ela não reflete um prazo configurado na diretriz.

Tarefas e questionários compartilham o type: Task da referência, e se distinguem pelo system do identificador. Nos dois casos o item é lido como Tarefa — o questionário do plano é uma tarefa atribuída ao paciente, não a resposta dele. As respostas são outro recurso, o Questionário respondido, e não é para ele que esta referência aponta.

Um item pode vir sem reference, sem progress e sem detail. Acontece quando o item já tem agendamento, mas o agendamento está num estado que esta integração não representa.

Qual identificador as referências de activity carregam depende da mesma configuração de implantação que vale para subject: com identificadores externos ligados, vem o identificador do seu sistema; sem ela, o identificador Nilo. Confira numa resposta real antes de casar as referências com os seus registros.

Um plano na fila ou ainda em geração (status: on-hold) volta sem activity. A lista vazia não significa diretriz sem itens: significa que a geração não terminou. Não conclua nada sobre o conteúdo de um plano até ele estar active.

Buscar

GET
/fhir/resources/CarePlan
1curl -G https://landing-zone-api.nilo.services/fhir/resources/CarePlan \
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 date=ge2026-01-01 \
7 --data-urlencode identifier=https://www.acmesaude.com.br/integracao/plano-de-cuidado/|349223 \
8 --data-urlencode instantiates-canonical=https://landing-zone-api.nilo.services/fhir/resources/PlanDefinition/aba72582-f9fb-49ea-b316-73b8dba2a4d7 \
9 --data-urlencode status=active,on-hold \
10 --data-urlencode subject=Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4 \
11 --data-urlencode subject.identifier=https://www.acmesaude.com.br/integracao/paciente/|507823709

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/CarePlan/3f21a0d5-9c74-4b18-a6e2-51d8c93f7ab0",
7 "resource": {
8 "instantiatesCanonical": [
9 "https://landing-zone-api.nilo.services/fhir/resources/PlanDefinition/aba72582-f9fb-49ea-b316-73b8dba2a4d7"
10 ],
11 "intent": "order",
12 "resourceType": "CarePlan",
13 "status": "active",
14 "subject": {
15 "identifier": {
16 "system": "https://www.acmesaude.com.br/integracao/paciente/",
17 "value": "507823709",
18 "use": "usual"
19 },
20 "type": "Patient",
21 "reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4"
22 },
23 "activity": [
24 {
25 "detail": {
26 "description": "Medicina de Família e Comunidade",
27 "kind": "Appointment",
28 "scheduledPeriod": {
29 "end": "2026-05-11",
30 "start": "2026-05-04"
31 },
32 "status": "not-started"
33 }
34 },
35 {
36 "progress": [
37 {
38 "text": "scheduled"
39 }
40 ],
41 "reference": {
42 "identifier": {
43 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--scheduling-v2",
44 "value": "702914",
45 "use": "usual"
46 },
47 "type": "Appointment"
48 }
49 },
50 {
51 "progress": [
52 {
53 "text": "in-progress"
54 }
55 ],
56 "reference": {
57 "identifier": {
58 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/cogsworth-api--to-do",
59 "value": "88214",
60 "use": "usual"
61 },
62 "type": "Task"
63 }
64 },
65 {
66 "progress": [
67 {
68 "text": "requested"
69 }
70 ],
71 "reference": {
72 "identifier": {
73 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/hippocrates-api--patient-questionnaire",
74 "value": "31905",
75 "use": "usual"
76 },
77 "type": "Task"
78 }
79 },
80 {
81 "progress": [
82 {
83 "text": "completed"
84 }
85 ],
86 "reference": {
87 "identifier": {
88 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/jaiminho-api--scheduled-message",
89 "value": "55407",
90 "use": "usual"
91 },
92 "type": "CommunicationRequest"
93 }
94 }
95 ],
96 "category": [
97 {
98 "text": "care_line"
99 }
100 ],
101 "created": "2026-04-16",
102 "description": "Acompanhamento longitudinal de pacientes com diabetes tipo 2.",
103 "id": "3f21a0d5-9c74-4b18-a6e2-51d8c93f7ab0",
104 "identifier": [
105 {
106 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/hippocrates-api--patient-care-line",
107 "value": "184532",
108 "use": "usual"
109 },
110 {
111 "system": "https://www.acmesaude.com.br/integracao/plano-de-cuidado/",
112 "value": "349223",
113 "use": "usual"
114 }
115 ],
116 "period": {
117 "start": "2026-04-16"
118 },
119 "title": "Diabetes tipo 2"
120 },
121 "search": {
122 "mode": "match"
123 }
124 }
125 ],
126 "link": []
127}

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 plano, em system|valueCarePlan.identifier
subject.identifiertokenPaciente, pelo identificador deleCarePlan.subject.identifier
subjectreferencePaciente, pelo id Nilo FHIRCarePlan.subject
instantiates-canonicalreferenceDiretriz, pela URL do PlanDefinitionCarePlan.instantiatesCanonical
statustokenSituação do plano. Aceita vários valores separados por vírgulaCarePlan.status
datedatePeríodo de aplicação, com os prefixos eq, ge, leCarePlan.period
_lastUpdateddateData da última gravação no store, com os mesmos prefixos

O par subject.identifier + instantiates-canonical é o que identifica o plano de um paciente numa diretriz — é a mesma busca que a própria plataforma usa para reconhecer um plano já existente:

$# o plano de um paciente numa diretriz, em qualquer estado não terminal
$curl --request GET \
> --url 'https://landing-zone-api.nilo.services/fhir/resources/CarePlan?subject.identifier=https://www.acmesaude.com.br/integracao/paciente/|507823709&instantiates-canonical=https://landing-zone-api.nilo.services/fhir/resources/PlanDefinition/aba72582-f9fb-49ea-b316-73b8dba2a4d7&status=active,on-hold,draft,entered-in-error' \
> --header 'x-api-key: SUA_API_KEY'

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.

Vários parâmetros canônicos da CarePlan existem e não encontram nada aqui, porque a Nilo não preenche o campo correspondente: care-team, condition, goal, encounter, based-on, replaces, part-of, performer, activity-code e activity-reference.

intent é um caso diferente: ele funciona, e por isso é inútil — o valor é constante, então intent=order traz todos os planos.

category é um caso à parte: o tipo da diretriz vem apenas como texto em category[0].text, sem coding. Uma busca por token no category não encontra o plano por care_line nem por protocol.

A paginação é por _count e _page_token; havendo página seguinte, o Bundle traz a URL pronta em link.

Ler por ID

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

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 plano está em resource. Ler status ou activity na raiz da resposta não encontra nada.

Response
1{
2 "fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/CarePlan/3f21a0d5-9c74-4b18-a6e2-51d8c93f7ab0",
3 "resource": {
4 "instantiatesCanonical": [
5 "https://landing-zone-api.nilo.services/fhir/resources/PlanDefinition/aba72582-f9fb-49ea-b316-73b8dba2a4d7"
6 ],
7 "intent": "order",
8 "resourceType": "CarePlan",
9 "status": "active",
10 "subject": {
11 "identifier": {
12 "system": "https://www.acmesaude.com.br/integracao/paciente/",
13 "value": "507823709",
14 "use": "usual"
15 },
16 "type": "Patient",
17 "reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4"
18 },
19 "activity": [
20 {
21 "progress": [
22 {
23 "text": "in-progress"
24 }
25 ],
26 "reference": {
27 "identifier": {
28 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/cogsworth-api--to-do",
29 "value": "88214",
30 "use": "usual"
31 },
32 "type": "Task"
33 }
34 }
35 ],
36 "category": [
37 {
38 "text": "care_line"
39 }
40 ],
41 "created": "2026-04-16",
42 "description": "Acompanhamento longitudinal de pacientes com diabetes tipo 2.",
43 "id": "3f21a0d5-9c74-4b18-a6e2-51d8c93f7ab0",
44 "identifier": [
45 {
46 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/hippocrates-api--patient-care-line",
47 "value": "184532",
48 "use": "usual"
49 },
50 {
51 "system": "https://www.acmesaude.com.br/integracao/plano-de-cuidado/",
52 "value": "349223",
53 "use": "usual"
54 }
55 ],
56 "meta": {
57 "lastUpdated": "2026-04-16T20:05:03.118000Z",
58 "versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
59 },
60 "period": {
61 "start": "2026-04-16"
62 },
63 "title": "Diabetes tipo 2"
64 },
65 "search": {
66 "mode": "match"
67 }
68}

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

Quando a alocação falha

A alocação em massa de uma diretriz pode falhar para um paciente específico — por exemplo, quando a equipe dele não cobre as especialidades exigidas. Nesse caso o plano passa a entered-in-error e o motivo da falha vem em note:

Response
1{
2 "fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/CarePlan/7b04e9c1-2d63-4f57-9a08-c1e5b7304d29",
3 "resource": {
4 "instantiatesCanonical": [
5 "https://landing-zone-api.nilo.services/fhir/resources/PlanDefinition/aba72582-f9fb-49ea-b316-73b8dba2a4d7"
6 ],
7 "intent": "order",
8 "resourceType": "CarePlan",
9 "status": "entered-in-error",
10 "subject": {
11 "identifier": {
12 "system": "https://www.acmesaude.com.br/integracao/paciente/",
13 "value": "507823709",
14 "use": "usual"
15 },
16 "type": "Patient",
17 "reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4"
18 },
19 "id": "7b04e9c1-2d63-4f57-9a08-c1e5b7304d29",
20 "identifier": [
21 {
22 "system": "https://www.acmesaude.com.br/integracao/plano-de-cuidado/",
23 "value": "349224",
24 "use": "usual"
25 }
26 ],
27 "note": [
28 {
29 "text": "Não há profissional com a especialidade exigida na equipe de cuidado do paciente."
30 }
31 ]
32 },
33 "search": {
34 "mode": "match"
35 }
36}

É o único caso em que note aparece num plano de cuidado. Um plano com note preenchido é sempre um plano que falhou.

Valores aceitos

status

Na escrita, draft, active, on-hold, completed, revoked e entered-in-error — com as restrições de transição descritas acima. unknown só aparece na leitura, num plano sem situação registrada na plataforma.

intent

O FHIR R4 exige o campo, e nada na integração o lê: ele não escolhe modo de aplicação nem nível de autoridade. É preenchimento obrigatório sem efeito. Envie order — é o valor que todas as leituras geradas pela plataforma trazem, e o que o resto da documentação assume.

category

Só resposta, e sem coding: o tipo da diretriz vem em category[0].text como care_line ou protocol.

Efeitos colaterais

status: active cria o plano na plataforma durante a requisição. É a única escrita desta página que altera o cadastro do paciente de forma imediata — e o que ela dispara em seguida (geração de tarefas, agendamentos, questionários e mensagens) acontece de forma assíncrona, fora do controle da chamada.

revoked e completed tiram o paciente do acompanhamento e são irreversíveis. O plano deixa de estar em execução e não aceita mais nenhuma atualização. O que acontece com as tarefas e mensagens ainda não executadas é decidido pela plataforma, fora do alcance desta chamada — não conte com elas depois de encerrar o plano.

Um identifier novo num paciente já alocado não cria plano. A chamada responde 200 com o plano existente e a sua chave anexada a ele. Veja a tabela em Como a API reconhece o plano.

Este endpoint não remove planos: a escrita nunca responde 204. O que existe é o cancelamento, por revoked — e ele preserva o registro no histórico do paciente.

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.

codeexpressionMensagemQuando
structureCarePlan.?patient_without_care_teamO paciente não tem equipe de cuidado
structureCarePlan.?todo_without_responsibleA equipe não cobre uma especialidade que a diretriz exige
structureCarePlan.subjectPatient with identifier … does not exist or is not activeO identificador do paciente não resolve
structureCarePlan.subjectMultiple Patient with identifier … foundO identificador casa com mais de um paciente
structureCarePlan.subjectOnly Patient type is supported.subject.type diferente de Patient
structureCarePlan.subjectPatient with nilo identifier does not existO paciente existe no store mas não tem identificador Nilo
structureCarePlan.instantiatesCanonicalinstantiatesCanonical is required.Campo ausente
structureCarePlan.instantiatesCanonicalPlanDefinition referenced by … does not exist or is not activeA URL da diretriz não resolve
structureCarePlan.instantiatesCanonicalPlanDefinition with id … does not point to an active care lineA diretriz existe, mas está fora da vigência
structureCarePlan.instantiatesCanonicalPlanDefinition with id … does not have an allocation configSó com draft: a diretriz não tem configuração de fila
structureCarePlan.statusCarePlan can only be created with status draft or activeCriação com qualquer outro status
structureCarePlan.statusCarePlan can't be updated to status …Plano existente voltando para draft ou active
structureCarePlan.statusCarePlan with status … can't be updated.Plano já revoked ou completed
structureCarePlan.authorOnly Practitioner type is supported.author.type diferente de Practitioner
structureCarePlan.authorPractitioner with identifier … does not exist or is not activeO author enviado não resolve
structureCarePlan.NoneCarePlan with nilo identifier does not existO plano alcançado não tem identificador Nilo — o caso comum é atualizar um plano ainda em draft
structureCarePlan.NonePlanDefinition with nilo identifier does not existA diretriz existe no store, mas sem identificador Nilo
structureCarePlan.authorPractitioner with nilo identifier does not existO profissional de author existe no store, mas sem identificador Nilo
exceptionIntegrityError: has more than one Care Plan …Mais de um plano não terminal para o par paciente + diretriz

Os payloads completos estão na aba Referência, em POST /fhir/resources/CarePlan.

Response
1{
2 "issue": [
3 {
4 "code": "structure",
5 "details": {
6 "text": "patient_without_care_team"
7 },
8 "expression": [
9 "CarePlan.?"
10 ],
11 "severity": "error"
12 }
13 ],
14 "resourceType": "OperationOutcome"
15}

Cinco linhas da tabela trazem expression que não é FHIRPath válido: as duas de CarePlan.?, que vêm da plataforma, e as três de CarePlan.None. Some-se a elas a linha de exception, que vem sem expression nenhum. Um integrador que usa o expression para destacar o campo culpado precisa tratar esses casos à parte.

Limite de escrita

A aplicação imediata (status: active) pode ser limitada por janela de tempo, para todo o seu ambiente. Atingido o limite, a resposta é 429 com o code throttled e o tempo de espera na mensagem — aguarde e repita. As demais escritas deste recurso não entram nessa conta.

O limite vigente é definido na implantação, e pode estar desligado. Se você vai fazer uma carga em volume, confirme com o Suporte qual é o teto do seu ambiente antes de dimensionar.