Skip to navigation

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
curl -G https://landing-zone-api.nilo.services/fhir/resources/InsurancePlan \
-H "x-api-key: <apiKey>" \
-d _count=50 \
-d _lastUpdated=eq2013-01-14 \
--data-urlencode identifier=https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--insurance-v2|2481 \
-d name=Ambulatorial \
-d status=active
Response
{
"resourceType": "Bundle",
"type": "searchset",
"entry": [
{
"fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/InsurancePlan/61a4c8d2-9e35-47bb-a0f1-2c7d5e8b3f90",
"resource": {
"resourceType": "InsurancePlan",
"identifier": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--insurance-v2",
"value": "2481",
"use": "usual"
}
],
"name": "Acme Saúde Ambulatorial",
"id": "61a4c8d2-9e35-47bb-a0f1-2c7d5e8b3f90",
"status": "active"
},
"search": {
"mode": "match"
}
},
{
"fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/InsurancePlan/0d7f3e51-8c26-4a90-bb14-7e5a1c9d2408",
"resource": {
"resourceType": "InsurancePlan",
"identifier": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--insurance-v2",
"value": "1907",
"use": "usual"
}
],
"name": "Acme Saúde Básico (encerrado)",
"id": "0d7f3e51-8c26-4a90-bb14-7e5a1c9d2408",
"status": "retired"
},
"search": {
"mode": "match"
}
}
],
"link": []
}

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

"class": [
{
"type": { "text": "plan" },
"value": "2481"
}
]

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

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
curl -X POST https://landing-zone-api.nilo.services/fhir/resources/InsurancePlan \
-H "x-api-key: <apiKey>" \
-H "Content-Type: application/json" \
-d '{
"resourceType": "InsurancePlan",
"identifier": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--insurance-v2",
"value": "2481",
"use": "usual"
}
],
"name": "Acme Saúde Ambulatorial Plus"
}'

A resposta é o recurso gravado, sem envelope:

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

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
curl https://landing-zone-api.nilo.services/fhir/resources/InsurancePlan/id \
-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
{
"fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/InsurancePlan/61a4c8d2-9e35-47bb-a0f1-2c7d5e8b3f90",
"resource": {
"resourceType": "InsurancePlan",
"identifier": [
{
"system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--insurance-v2",
"value": "2481",
"use": "usual"
}
],
"name": "Acme Saúde Ambulatorial",
"id": "61a4c8d2-9e35-47bb-a0f1-2c7d5e8b3f90",
"meta": {
"lastUpdated": "2026-08-24T12:04:18.911000Z",
"versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
},
"status": "active"
},
"search": {
"mode": "match"
}
}

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.Há identifier, mas nenhum utilizável — falta system ou falta value
structure—Resource 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
exception—HTTPServerError: [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
{
"issue": [
{
"code": "exception",
"details": {
"text": "HTTPServerError: [Server Error] 500 for https://<serviço>/api/v2/care/insurances/: <corpo da resposta>"
},
"severity": "error"
}
],
"resourceType": "OperationOutcome"
}

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.