Plano de saúde

Um plano de saúde aqui é uma entrada no catálogo do seu ambiente: o convênio, o plano ou o benefício que custeia o atendimento de um paciente. Cada cobertura aponta para um deles, e é o nome cadastrado aqui que a equipe vê no campo Plano de saúde da ficha do paciente.

No FHIR o recurso é o InsurancePlan. Na prática ele serve para duas coisas: descobrir o id do plano que vai na cobertura, e corrigir o nome de um plano que já existe.

Planos novos não são criados por esta API. O catálogo é montado na implantação do seu ambiente, junto com o time da Nilo. O POST desta página encontra um plano pelo identifier e altera o nome dele; um identifier que não corresponda a nenhum plano existente não cria nada — a chamada é recusada. Para incluir um plano no catálogo, fale com o Suporte.

Campos

CampoObrigatórioO que significaNo Nilo Care
resourceTypesimConstante InsurancePlan
identifiersimIdentificador do plano. É por ele que a API encontra o plano a alterar
namesimNome do plano, com no máximo 200 caracteresPlano de saúde, na cobertura do paciente
statusnãoSó resposta: active num plano em uso, retired num plano desativado
id · metanãoSó resposta: identificador Nilo FHIR do plano e metadados da gravação

status não é gravável. Ativar ou desativar um plano é decisão da plataforma, e enviar status no payload não muda nada — o valor que volta continua sendo o que a plataforma calcula. Não há como aposentar um plano por esta API.

O status é informativo, e não restringe nada: um plano retired continua aparecendo na busca e continua sendo aceito em Coverage.class[0].value. Se a sua integração precisa oferecer só planos vigentes, filtre por status=active do seu lado — a plataforma não recusa o outro.

Campos que a Nilo não usa

O InsurancePlan canônico traz muito mais do que esta integração lê: type, alias, period, ownedBy, administeredBy, coverageArea, contact, endpoint, network, coverage e plan. Nenhum deles é lido, e por isso nenhum aparece na referência do recurso.

A referência lista só os campos suportados, e é assim que ela deve ser lida: o que mandar na escrita. A API em si não recusa quem manda os outros — eles ficam guardados no recurso e voltam nas leituras seguintes, sem nunca terem significado nada para a plataforma. Se o seu validador for estrito contra a referência, uma resposta assim vai parecer inválida; o remédio é não enviá-los.

Descobrir o id de um plano

Este é o uso principal do recurso. A cobertura de um paciente identifica o plano por class[0].value, e o valor esperado ali é o value do identificador Nilo do plano — o que vem no system …/NamingSystem/care-api--insurance-v2.

GET
/fhir/resources/InsurancePlan
1curl -G https://landing-zone-api.nilo.services/fhir/resources/InsurancePlan \
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://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--insurance-v2|2481 \
7 -d name=Ambulatorial \
8 -d status=active
Response
1{
2 "resourceType": "Bundle",
3 "type": "searchset",
4 "entry": [
5 {
6 "fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/InsurancePlan/61a4c8d2-9e35-47bb-a0f1-2c7d5e8b3f90",
7 "resource": {
8 "resourceType": "InsurancePlan",
9 "identifier": [
10 {
11 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--insurance-v2",
12 "value": "2481",
13 "use": "usual"
14 }
15 ],
16 "name": "Acme Saúde Ambulatorial",
17 "id": "61a4c8d2-9e35-47bb-a0f1-2c7d5e8b3f90",
18 "status": "active"
19 },
20 "search": {
21 "mode": "match"
22 }
23 },
24 {
25 "fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/InsurancePlan/0d7f3e51-8c26-4a90-bb14-7e5a1c9d2408",
26 "resource": {
27 "resourceType": "InsurancePlan",
28 "identifier": [
29 {
30 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--insurance-v2",
31 "value": "1907",
32 "use": "usual"
33 }
34 ],
35 "name": "Acme Saúde Básico (encerrado)",
36 "id": "0d7f3e51-8c26-4a90-bb14-7e5a1c9d2408",
37 "status": "retired"
38 },
39 "search": {
40 "mode": "match"
41 }
42 }
43 ],
44 "link": []
45}

No exemplo acima, uma cobertura no plano Acme Saúde Ambulatorial levaria:

1"class": [
2 {
3 "type": { "text": "plan" },
4 "value": "2481"
5 }
6]

Quem não quer carregar o id Nilo do plano pode usar a extensão insurance-plan da cobertura, que aceita qualquer identificador de um plano já cadastrado — inclusive o do seu próprio sistema, se ele tiver sido gravado no plano. Veja Cobertura e Extensões.

Os planos cadastrados na implantação trazem apenas o identificador Nilo. Um plano só passa a ter a sua chave se você a tiver gravado nele por integração — e como esta API não cria planos, isso só vale para os que já existiam quando você mandou o POST.

Buscar

A resposta é sempre um Bundle do tipo searchset, e 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|valueInsurancePlan.identifier
namestringParte do nome do planoInsurancePlan.name
statustokenactive ou retiredInsurancePlan.status
_lastUpdateddateData da última gravação no store, com os prefixos eq, ge, le

Os demais parâmetros canônicos do InsurancePlan existem e não encontram nada aqui, porque a Nilo não preenche o campo correspondente: type, owned-by, administered-by, endpoint e os de endereço. A exceção é o campo que você mesmo tenha enviado: ele fica no recurso e passa a ser encontrável — mais um motivo para omitir o que a plataforma não usa.

Os catálogos costumam ser pequenos, e a chamada mais comum é listar tudo:

$curl --request GET \
> --url 'https://landing-zone-api.nilo.services/fhir/resources/InsurancePlan' \
> --header 'x-api-key: SUA_API_KEY'

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

Um plano antigo, que ninguém tenha tocado desde que a sua integração começou, pode não aparecer na lista — e, não aparecendo, também não pode ser renomeado, porque o POST não consegue encontrá-lo. Se você espera um plano e ele não vem, peça ao Suporte: a busca não é um inventário garantido do catálogo.

Renomear um plano

POST
/fhir/resources/InsurancePlan
1curl -X POST https://landing-zone-api.nilo.services/fhir/resources/InsurancePlan \
2 -H "x-api-key: <apiKey>" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "resourceType": "InsurancePlan",
6 "identifier": [
7 {
8 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--insurance-v2",
9 "value": "2481",
10 "use": "usual"
11 }
12 ],
13 "name": "Acme Saúde Ambulatorial Plus"
14}'

A resposta é o recurso gravado, sem envelope:

Response
1{
2 "resourceType": "InsurancePlan",
3 "identifier": [
4 {
5 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--insurance-v2",
6 "value": "2481",
7 "use": "usual"
8 }
9 ],
10 "name": "Acme Saúde Ambulatorial Plus",
11 "id": "61a4c8d2-9e35-47bb-a0f1-2c7d5e8b3f90",
12 "meta": {
13 "lastUpdated": "2026-08-24T12:04:18.911000Z",
14 "versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
15 },
16 "status": "active"
17}

O name é o único dado gravado. status e qualquer outro campo do payload são descartados.

Renomear muda o nome em todas as coberturas que apontam para o plano. O plano é um só, compartilhado por todos os pacientes que o usam — não há um nome por paciente. Um erro de digitação aqui aparece na ficha de todo mundo.

O identifier que localiza o plano pode ser o identificador Nilo dele ou uma chave sua que já esteja gravada no plano. Mandando uma chave nova junto com o identificador Nilo, as duas passam a valer para aquele plano — é assim que você anexa a sua própria chave a um plano do catálogo.

Ler por ID

GET
/fhir/resources/InsurancePlan/:id
1curl https://landing-zone-api.nilo.services/fhir/resources/InsurancePlan/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 name na raiz da resposta não encontra nada.

Response
1{
2 "fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/InsurancePlan/61a4c8d2-9e35-47bb-a0f1-2c7d5e8b3f90",
3 "resource": {
4 "resourceType": "InsurancePlan",
5 "identifier": [
6 {
7 "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--insurance-v2",
8 "value": "2481",
9 "use": "usual"
10 }
11 ],
12 "name": "Acme Saúde Ambulatorial",
13 "id": "61a4c8d2-9e35-47bb-a0f1-2c7d5e8b3f90",
14 "meta": {
15 "lastUpdated": "2026-08-24T12:04:18.911000Z",
16 "versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
17 },
18 "status": "active"
19 },
20 "search": {
21 "mode": "match"
22 }
23}

Valores aceitos

status

Dois: active e retired. São só resposta — a plataforma os calcula, e nenhum dos dois pode ser enviado para mudar a situação de um plano. Os outros valores do FHIR R4 (draft, unknown) não são usados.

Nenhum dos dois bloqueia nada: um plano retired continua listado e continua servindo a uma cobertura nova. O valor é um sinal de catálogo, não uma regra de negócio aplicada pela API.

Efeitos colaterais

Renomear um plano não muda nenhuma cobertura: as coberturas continuam apontando para o mesmo plano, e o Nilo Care passa a exibir o nome novo em todas elas. Nenhum paciente é afetado além do rótulo.

Na API, porém, o nome novo não alcança as coberturas já gravadas. A leitura de uma cobertura traz em class[0].name o nome que o plano tinha quando aquela cobertura foi gravada pela última vez, e renomear o plano não reescreve as coberturas. O class[0].name só acompanha o nome novo depois que a cobertura for gravada de novo, por qualquer motivo.

Para o nome atual de um plano, leia o InsurancePlan — nunca o class[0].name de uma cobertura. O class[0].value, esse sim, continua correto e é o que liga os dois.

Este endpoint nunca responde 204: não há remoção de plano por integração.

Erros

Recusa é 400, e o corpo é um OperationOutcome: issue[].details.text explica o motivo e, quando a recusa é de um campo conferido por esta API, issue[].expression aponta qual.

codeexpressionMensagemQuando
requiredInsurancePlan.identifierField is requiredO payload não tem identifier
business-ruleInsurancePlan.identifierUnable to use any of the provided identifiers to match an existing resource, which can lead to duplicates.identifier, mas nenhum utilizável — falta system ou falta value
structureResource has identifier from a Nilo environment that is not the current environment.O payload traz um identificador Nilo gerado em outro ambiente
structureo campo recusadomensagem da validação FHIRO payload não é um InsurancePlan válido
exceptionHTTPServerError: [Server Error] 500 for … ou HTTPBadRequest: …O identifier não corresponde a nenhum plano do catálogo, o name está ausente, ou passa de 200 caracteres
Response
1{
2 "issue": [
3 {
4 "code": "exception",
5 "details": {
6 "text": "HTTPServerError: [Server Error] 500 for https://<serviço>/api/v2/care/insurances/: <corpo da resposta>"
7 },
8 "severity": "error"
9 }
10 ],
11 "resourceType": "OperationOutcome"
12}

A última linha não é uma validação desta API — é a recusa da própria plataforma, repassada como está. Ela sai com code: exception, sem expression, e com uma mensagem de erro de linguagem, que inclui o endereço interno chamado. Nada disso é contrato: não tente interpretar o texto, não o exiba para o usuário final e não o registre em log de longa duração. Trate code: exception como “payload recusado, motivo não classificado” e confira antes, com um GET, se o plano que você quer alterar existe.

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