Equipe de cuidado
Uma equipe de cuidado é o grupo de profissionais responsável por acompanhar um paciente: quem está nela e com que especialidade cada um atua. O vínculo é o outro lado da mesma moeda — qual equipe acompanha qual paciente, e desde quando.
No FHIR as duas coisas são o mesmo recurso,
CareTeam, e é o campo subject que diz qual delas
você está manipulando.
A equipe de cuidado é pré-requisito de boa parte do produto: um paciente sem equipe não recebe plano de cuidado, e a aplicação de uma diretriz é recusada se a equipe dele não cobrir as especialidades exigidas — veja Plano de cuidado.
As duas formas do recurso
As duas formas convivem no mesmo endpoint e no mesmo conjunto de dados: uma busca sem filtro
devolve equipes e vínculos misturados. Use identificadores distintos para cada uma. Se a
sua chave do vínculo for igual à chave da equipe, a escrita alcança o registro errado — e não
há erro, porque do ponto de vista do FHIR os dois são um CareTeam com aquele identifier.
Campos
A coluna Onde diz em qual das duas formas o campo é lido. 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.
Campos que a Nilo não usa
A CareTeam canônica traz mais do que esta integração lê: category, encounter, note,
reasonCode, reasonReference, telecom, e ainda participant[].onBehalfOf,
participant[].period e participant[].id. Nenhum deles é lido, e por isso nenhum aparece na
referência do recurso.
Enviá-los não é erro, e nenhum deles tem efeito — um period dentro de um participant, por
exemplo, não limita a participação daquele profissional na equipe. Os campos de topo (note,
telecom, category, encounter, reasonCode, reasonReference) ficam guardados no recurso
e voltam nas leituras seguintes. Os que ficam dentro de participant[] não: quando a
plataforma regrava a equipe, ela reescreve a lista de participantes inteira, e
onBehalfOf, period e id desaparecem com ela.
Montar a equipe
Não há endpoint separado para criar e atualizar: o mesmo POST faz os dois, e a equipe é
reconhecida pelo identifier.
A resposta é o recurso gravado, sem envelope:
Guarde o id: é por ele que se faz a leitura direta. Ao lado do seu identifier, a resposta
traz o identificador Nilo da equipe, no system
…/NamingSystem/sorting-hat-api--care-team.
A resposta da escrita repete o que você enviou — ela não confirma o que a plataforma
registrou. Na gravação, todo campo presente no seu payload vence a visão da plataforma:
participant, role, name, status e period voltam como foram mandados, acrescidos apenas
de id, meta e do identificador Nilo. Um profissional que a plataforma descartou continua
aparecendo na resposta, e as referências (member.reference) não vêm.
Para saber como a equipe ficou de fato, leia a equipe depois — por id ou por
identifier. A leitura é o que reflete a plataforma; a resposta da escrita, não.
Sem identifier que case, a chamada cria uma equipe nova. Não há reconhecimento por
composição de profissionais nesta forma do recurso: mandar duas vezes a mesma equipe com
chaves diferentes produz duas equipes com os mesmos integrantes. Mande sempre a sua chave, e a
mesma chave.
Os profissionais e as especialidades
Cada item de participant é um profissional, e role são as especialidades com que ele atua
naquela equipe. Um profissional com duas especialidades no time vai num único participant,
com dois itens em role.
Repetir o mesmo profissional em dois participant também funciona: as especialidades dos dois
itens são somadas, e o resultado é o mesmo de um item com dois role. É o que permite reenviar,
sem tratamento, a forma que a leitura devolve.
Três condições, todas verificadas na chamada:
member.typetem de serPractitioner. Na escrita da equipe nenhum outro tipo é aceito.- O profissional tem de existir e estar ativo — é o cadastro de Profissional que responde por isso.
- O profissional tem de pertencer à unidade de cuidado da equipe. Um profissional fora dela recusa a chamada inteira.
A atualização substitui a composição, não a complementa. Todo par profissional +
especialidade que não vier no participant é removido da equipe. Para trocar um integrante,
reenvie a formação completa — inclusive quem não mudou.
A chave participant tem de estar presente: um payload sem ela é recusado com
participant of the CareTeam is required. Uma lista vazia ([]) é aceita pela regra de negócio
e esvazia a equipe — todos os integrantes são removidos e a equipe continua existindo, sem
ninguém. Mas o padrão FHIR não admite array vazio, e a validação do recurso acontece antes
dessa regra: se você precisa esvaziar uma equipe pela API, confirme esse caminho com o Suporte
antes de contar com ele.
Um role cujo coding não esteja em CBO nem em SNOMED CT é ignorado em silêncio, e o
profissional acaba fora da equipe: sem especialidade reconhecida, não há o que registrar. A
chamada responde 200, e — como a resposta repete o payload — ela ainda mostra o
profissional. Só uma leitura posterior revela que ele não entrou. Já um código dentro
desses sistemas que não esteja mapeado recusa a chamada, com mensagem explícita — veja
Erros.
A unidade de cuidado
A unidade vem em managingOrganization[].identifier, e só é reconhecida no system
…/NamingSystem/sorting-hat-api--care-unit — o identificador Nilo da unidade. Omitida, ou
informada em outro system, a unidade padrão da sua implantação é usada.
A unidade de cuidado não muda depois da criação. Numa atualização ela é usada apenas para
validar os profissionais enviados; a unidade gravada na equipe continua a mesma. E como a
validação é feita contra a unidade do payload, omitir managingOrganization numa atualização
faz a chamada ser validada contra a unidade padrão — se a equipe não for dela, os
profissionais são recusados por não pertencerem “a nenhuma unidade de cuidado”. Envie sempre a
mesma unidade que você usou na criação.
Aqui a sua própria chave não serve. Ao contrário do Paciente e
do Profissional, que aceitam qualquer identificador da unidade,
a equipe de cuidado só lê o identificador Nilo. Um managingOrganization com o identificador
do seu sistema é ignorado em silêncio, e a equipe acaba na unidade padrão — ou a chamada é
recusada com Managing organization not found. se não houver padrão configurado.
Havendo mais de um item em managingOrganization, vale o último cujo system seja o
identificador Nilo, não o primeiro.
Para descobrir as unidades do seu ambiente e o identificador Nilo de cada uma, liste-as — veja Unidade de cuidado:
status na escrita da equipe não tem efeito sobre o cadastro: a equipe não tem vigência. Mas
o valor que você enviar fica no recurso FHIR e é lido de volta até a plataforma regravar a
equipe — o que pode levar horas, porque uma regravação sem mudança de conteúdo é dispensada.
Envie active, que é o valor que a plataforma produz.
Atribuir a equipe a um paciente
Com subject, a mesma escrita passa a ser o vínculo entre o paciente e uma equipe. Há duas
formas, escolhidas pelo member.type do participant.
Apontando uma equipe existente
member.type igual a CareTeam, com o identificador da equipe. É a forma previsível: o
vínculo aponta uma equipe que você já criou.
A equipe precisa existir antes. Não existindo, a chamada é recusada — mas o erro sai como
code: exception, com uma mensagem de linguagem no lugar de uma explicação do campo. Crie a
equipe primeiro e confirme o identifier dela antes de atribuí-la.
Compondo pelos profissionais
member.type igual a Practitioner em todos os participantes, cada um com o seu role. A
plataforma procura uma equipe cuja composição de profissionais e especialidades seja
exatamente a que você enviou e, achando, vincula o paciente a ela.
Não achando, uma equipe nova é criada. É o efeito colateral mais fácil de disparar sem
querer: uma especialidade a mais ou a menos já faz a composição não casar, e o resultado é uma
equipe nova — com o name que você mandou, ou um nome aleatório — em vez do vínculo com a
equipe que você tinha em mente. Se a intenção é reusar uma equipe, aponte-a pelo
member.type: CareTeam.
A equipe reaproveitada é reescrita. Antes de comparar composições, a API tenta reencontrar o
vínculo pelo identifier que você mandou; achando, reusa a equipe que ele já apontava. Mas em
seguida essa equipe recebe o name do payload e tem a composição substituída pela que você
enviou, par a par — exatamente como numa atualização da equipe. Reenviar o vínculo com um
profissional a menos remove esse profissional da equipe, para todos os pacientes ligados a
ela.
Se a sua intenção é só trocar o paciente de equipe, aponte a equipe por member.type: CareTeam:
essa forma não mexe na composição.
Nesta forma, um profissional que não pertence à unidade de cuidado é descartado em
silêncio: ele é validado como profissional, mas fica de fora da equipe montada, e a chamada
responde 200. É diferente da escrita da equipe, onde o mesmo caso é recusado com erro.
Confira a composição da equipe criada antes de considerar a atribuição concluída.
Um participant vazio também é aceito aqui, e vincula o paciente a uma equipe nova sem
nenhum profissional. Como um paciente sem profissionais na equipe não recebe plano de
cuidado, essa combinação raramente é o que se quer.
Vigência: status e period
O status é a instrução, e o period é o registro. Enviando um sem o outro, o status
decide as datas:
Havendo period no payload, três regras são conferidas:
period.endnão pode ser enviado comstatus: active;period.endtem de ser anterior ao momento da chamada;- o período tem de ser coerente com o
status— um período vigente não pode vir marcado comoinactive, nem o contrário.
Na leitura, o status é derivado do período: active quando o momento da leitura cai
dentro dele, inactive fora. Um vínculo sem datas é lido como active.
Criar um vínculo encerra um vínculo anterior do paciente. A plataforma fecha um dos vínculos existentes com a data e hora da chamada antes de registrar o novo — não é preciso encerrá-lo antes, e não há aviso na resposta de que isso aconteceu. Um paciente tem uma equipe por vez.
O vínculo escolhido não é necessariamente o vigente: é o primeiro que a plataforma encontra para
aquele paciente. Num paciente com histórico de vínculos, isso pode reescrever a data de fim de um
vínculo já encerrado. Encerre você mesmo o vínculo vigente, com status: inactive, antes de
atribuir a equipe nova — é o caminho previsível.
O encerramento automático vale para a criação de um vínculo, não para a atualização de um
que já existe. Reenviar um vínculo que a API reconheça pelo identifier atualiza aquele
registro e não mexe em nenhum outro.
Quando o encerramento automático não resolve a situação — por exemplo, um paciente com mais de
um vínculo em aberto —, a escrita é recusada com
This patient already belongs to an unfinished care team, e nada é gravado. Nesse caso encerre
os vínculos abertos explicitamente, com status: inactive, antes de atribuir a equipe nova.
Encerrar o vínculo
Reenvie o vínculo com status: inactive e sem period:
Depois disso o paciente fica sem equipe de cuidado até uma nova atribuição — e sem equipe ele não entra em diretriz nova e não recebe itens de plano de cuidado. Encerrar sem atribuir outra equipe interrompe o acompanhamento.
Buscar
A resposta é sempre um Bundle do tipo searchset, com equipes e vínculos misturados:
Busca sem resultados não é erro: volta 200 com um Bundle cujo entry é uma lista vazia.
Trate a ausência de resultados pela lista vazia, não esperando um 404.
Parâmetros de busca suportados
A busca mais usada é a do vínculo vigente de um paciente:
status=inactive traz apenas vínculos, e só os encerrados: a equipe de cuidado sai sempre
como active. Não há, do outro lado, um filtro que traga apenas equipes — para separá-las dos
vínculos, olhe a presença de subject em cada entrada do resultado.
Qual identificador as referências carregam depende da sua implantação. Na configuração que
usa identificadores externos nas referências, subject e participant[].member trazem o
identificador do seu sistema, e os filtros acima funcionam como estão. Sem ela, vêm os
identificadores Nilo (…/NamingSystem/hippocrates-api--patient,
…/NamingSystem/almanac-api--professional), 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.
Dois parâmetros canônicos da CareTeam existem e não encontram nada aqui, porque a Nilo
não preenche o campo correspondente: category e encounter.
A paginação é por _count e _page_token; havendo página seguinte, o Bundle traz a URL
pronta em link.
Ler por ID
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 a equipe está em
resource. Ler participant ou status na raiz da resposta não encontra nada.
A leitura da equipe quebra um profissional com várias especialidades em vários
participant. Você escreve um item com dois role; a leitura devolve dois itens com o mesmo
member e um role cada. Não é perda de dado — reenviar o que foi lido reconstrói a mesma
composição —, mas quem conta participant para saber o tamanho da equipe conta errado. Conte
member distintos.
Cada role lido traz um coding, e text com o nome da ocupação naquele catálogo — não o
nome da especialidade na plataforma. Uma especialidade mapeada nos dois catálogos sai como dois
itens de role, um por sistema, e não como um item com dois coding.
A leitura por ID responde 404 quando o id não existe.
Valores aceitos
participant[].role
Dois sistemas de codificação, e só eles:
Dentro de um item de role, o primeiro coding num desses dois sistemas é o que vale — os
demais são ignorados. Um código em qualquer outro system é ignorado, e um item de role só
com códigos ignorados não registra especialidade nenhuma.
Nem todo código dos dois catálogos é utilizável: o código precisa estar mapeado para uma
especialidade da plataforma. Não estando, a chamada é recusada com
BOC code … does not exist or it is not mapped ou SNOMED code … does not exist or it is not mapped.
status
active e inactive — são os dois únicos valores que a leitura produz e os dois únicos com
efeito na escrita.
Os demais valores do FHIR R4 (proposed, suspended, entered-in-error) não são recusados:
eles caem no mesmo caminho de um status ausente, e num vínculo novo isso grava um vínculo
sem datas, que a leitura seguinte devolve como active. Não use nenhum deles esperando que o
vínculo fique inativo — só inactive encerra.
Efeitos colaterais
Atribuir uma equipe a um paciente encerra o vínculo vigente dele. O vínculo anterior é fechado com a data e hora da chamada, sem aviso na resposta.
Atualizar a equipe remove quem não foi enviado. A composição enviada substitui a existente, par a par (profissional + especialidade).
Atribuir uma equipe pelos profissionais pode criar uma equipe nova. Sem uma equipe cuja composição case exatamente com a enviada, uma é criada — e passa a existir no cadastro de equipes da unidade.
Este endpoint não remove equipes nem vínculos: a escrita nunca responde 204. O que existe é
o encerramento do vínculo, por status: inactive, 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.
Os payloads completos estão na aba Referência, em POST /fhir/resources/CareTeam.
As duas últimas linhas da tabela não são validações — são falhas não tratadas, e a segunda é
o caso comum de identificador errado, não uma raridade. O 400 sai com code: exception, sem
expression, e com uma mensagem de erro de linguagem em vez de uma explicação do campo. As
mensagens específicas de paciente e de equipe inexistentes estão na tabela porque o código as
produz, mas elas dependem de o repositório de recursos responder “não encontrado” — quando o
identificador apenas não casa com nada, o que você recebe é o exception.
Nenhuma das duas é contrato: não tente interpretá-las. Trate code: exception como “payload
recusado, motivo não classificado”, e confira os identificadores enviados.
Limite de escrita
As escritas deste recurso podem ser limitadas 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.
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.

