> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://api-docs.nilo.services/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://api-docs.nilo.services/_mcp/server.

# Paciente

> Cadastrar, atualizar e buscar pacientes no padrão FHIR Patient.

O [`Patient`](https://hl7.org/fhir/R4/patient.html) carrega os dados demográficos e
administrativos de quem recebe cuidado. É o recurso central da integração: quase todo
outro recurso — atendimento, condição, diretriz aplicada — referencia um paciente.

## Campos

A coluna **No NiloCare** traz o rótulo com que o dado aparece para a equipe de cuidado.
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.

| Campo                                            | Obrigatório             | O que significa                                                                                     | No NiloCare                                                   |
| ------------------------------------------------ | ----------------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| `identifier`                                     | **sim**, ao menos um    | Chaves do paciente. É por aqui que a API decide entre criar e atualizar                             | —                                                             |
| `identifier` (CPF)                               | **sim** por padrão 3    | CPF, exatamente 11 dígitos                                                                          | **CPF**                                                       |
| `name[use=official]`                             | **sim** na criação      | Nome legal. Vale o `text`; na falta dele, `given` + `family`                                        | **Nome paciente**                                             |
| `name[use=usual]`                                | não                     | Nome social ou apelido                                                                              | **Nome Social (para pessoas trans, travestis e transexuais)** |
| `birthDate`                                      | não                     | Data de nascimento                                                                                  | **Data de Nascimento**                                        |
| `gender`                                         | não, mas reenvie 4      | Sexo administrativo. Só `male` e `female` são gravados                                              | **Sexo**                                                      |
| `maritalStatus`                                  | não                     | Estado civil                                                                                        | **Estado civil**                                              |
| `telecom[system=phone]`                          | não                     | Celular do paciente, com DDI + DDD + número (ex.: `5511987654321`). Passa por validação de WhatsApp | **Celular com Whatsapp**                                      |
| `telecom[system=email]`                          | não                     | E-mail de contato                                                                                   | **Email**                                                     |
| `address[0].line[0]`                             | não                     | Logradouro                                                                                          | **Logradouro**                                                |
| `address[0].line[1]`                             | não                     | Número. Ausente, é gravado como `S/N`                                                               | **Número**                                                    |
| `address[0].line[2]`                             | não                     | Complemento                                                                                         | **Complemento**                                               |
| `address[0].district`                            | não                     | Bairro                                                                                              | **Bairro**                                                    |
| `address[0].city`                                | não                     | Cidade                                                                                              | **Cidade**                                                    |
| `address[0].state`                               | não                     | Estado                                                                                              | **Estado**                                                    |
| `address[0].postalCode`                          | não                     | CEP                                                                                                 | **CEP**                                                       |
| `address[0].country`                             | não                     | País                                                                                                | —                                                             |
| `deceasedDateTime`                               | não                     | Data e hora do óbito                                                                                | —                                                             |
| `managingOrganization`                           | não                     | Unidade de cuidado responsável pelo paciente                                                        | **Unidade de cuidado**                                        |
| `contained[Group]`                               | **sim**, com ressalva 1 | Grupos a que o paciente pertence                                                                    | **Grupos de pacientes**                                       |
| `active`                                         | não                     | Se o cadastro está em uso. Traduz para o status do paciente                                         | **Status**                                                    |
| `extension` `patient-status`                     | não                     | Status do paciente pelo id de um status do seu care provider                                        | **Status**                                                    |
| `extension` `patient-isLead`                     | não                     | `true` = pré-cadastro, ainda pendente de aceite dos termos de uso                                   | **Já aceitou os termos de uso para ser paciente?**            |
| `extension` `patient-sendWelcomingMessage`       | **sim**, com ressalva 2 | Dispara ou não a mensagem de boas-vindas ao cadastrar                                               | **Enviar mensagem de boas vindas?**                           |
| `extension` `patient-createOnboardingScheduling` | **sim**, com ressalva 2 | Libera o paciente para o primeiro agendamento                                                       | **Liberar agendamento de onboarding?**                        |
| `extension` `patient-genderIdentity`             | não                     | Identidade de gênero, num vocabulário próprio                                                       | **Identidade de gênero**                                      |
| `extension` `patient-religion`                   | não                     | Espiritualidade declarada, em texto livre                                                           | **Espiritualidade**                                           |
| `extension` `patient-cadavericDonor`             | não                     | Se o paciente é doador de órgãos                                                                    | **Doador de órgãos**                                          |
| `communication`                                  | só resposta             | Idioma de contato. Sempre `pt-BR`                                                                   | —                                                             |
| `extension` `patient-paths`                      | só resposta             | Atalho para a ficha do paciente no NiloCare                                                         | —                                                             |

1 Todo paciente pertence a pelo menos um grupo, mas o payload pode omiti-lo se a
sua unidade de cuidado tiver grupo padrão configurado. Veja [Grupos](#grupos).\

2 Obrigatórias no envio, e preenchidas com o padrão da sua unidade de cuidado
quando omitidas. Sem valor enviado e sem padrão configurado, a escrita é recusada.\

3 O `system` do CPF vem configurado como identificador único do paciente por
padrão, e nessa configuração o CPF é obrigatório. Ele só é opcional se a sua implantação
usar outro identificador único — veja **CPF como identificador único**, adiante.\

4 `gender` é o único campo do recurso que **não** é preservado numa atualização
parcial: omiti-lo grava `other` por cima do sexo atual. Reenvie-o em toda escrita — veja
[Sexo](#sexo).

A URL completa de cada extensão está em [Extensões](/guia/conceitos/extensoes) — nesta
página elas aparecem só pelo nome final.

> **Warning**
>
> `Sexo` é de preenchimento obrigatório no cadastro pela interface, mas `gender` é opcional
> na API — e essa diferença tem uma consequência que foge à regra da atualização parcial.
> Um `Patient` enviado sem `gender` grava `other`, **inclusive num paciente que já tem sexo
> registrado**. Reenvie `gender` em toda escrita, mesmo quando o objetivo é atualizar outro
> campo. Veja [Sexo](#sexo).

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

### Request

POST [https://landing-zone-api.nilo.services/fhir/resources/Patient](https://landing-zone-api.nilo.services/fhir/resources/Patient)

**`Cadastro mínimo`**

```curl Cadastro mínimo
curl -X POST https://landing-zone-api.nilo.services/fhir/resources/Patient \
     -H "x-api-key: <apiKey>" \
     -H "Content-Type: application/json" \
     -d '{
  "identifier": [
    {
      "system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
      "value": "39053344705",
      "use": "official"
    },
    {
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709",
      "use": "usual"
    }
  ],
  "resourceType": "Patient",
  "extension": [
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/Group",
      "valueIdentifier": {
        "system": "https://www.acmesaude.com.br/integracao/grupo/",
        "use": "usual",
        "value": "diabeticos-tipo-2"
      }
    },
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-sendWelcomingMessage",
      "valueBoolean": true
    },
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-createOnboardingScheduling",
      "valueBoolean": true
    }
  ],
  "name": [
    {
      "family": "Silveira",
      "given": [
        "João"
      ],
      "use": "official"
    }
  ]
}'
```

**`Cadastro mínimo`**

```python Cadastro mínimo
import requests

url = "https://landing-zone-api.nilo.services/fhir/resources/Patient"

payload = {
    "identifier": [
        {
            "system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
            "value": "39053344705",
            "use": "official"
        },
        {
            "system": "https://www.acmesaude.com.br/integracao/paciente/",
            "value": "507823709",
            "use": "usual"
        }
    ],
    "resourceType": "Patient",
    "extension": [
        {
            "url": "https://landing-zone-api.nilo.services/fhir/resources/Group",
            "valueIdentifier": {
                "system": "https://www.acmesaude.com.br/integracao/grupo/",
                "use": "usual",
                "value": "diabeticos-tipo-2"
            }
        },
        {
            "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-sendWelcomingMessage",
            "valueBoolean": True
        },
        {
            "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-createOnboardingScheduling",
            "valueBoolean": True
        }
    ],
    "name": [
        {
            "family": "Silveira",
            "given": ["João"],
            "use": "official"
        }
    ]
}
headers = {
    "x-api-key": "<apiKey>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`Cadastro mínimo`**

```javascript Cadastro mínimo
const url = 'https://landing-zone-api.nilo.services/fhir/resources/Patient';
const options = {
  method: 'POST',
  headers: {'x-api-key': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"identifier":[{"system":"https://servicos.receita.fazenda.gov.br/servicos/cpf/","value":"39053344705","use":"official"},{"system":"https://www.acmesaude.com.br/integracao/paciente/","value":"507823709","use":"usual"}],"resourceType":"Patient","extension":[{"url":"https://landing-zone-api.nilo.services/fhir/resources/Group","valueIdentifier":{"system":"https://www.acmesaude.com.br/integracao/grupo/","use":"usual","value":"diabeticos-tipo-2"}},{"url":"https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-sendWelcomingMessage","valueBoolean":true},{"url":"https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-createOnboardingScheduling","valueBoolean":true}],"name":[{"family":"Silveira","given":["João"],"use":"official"}]}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

**`Cadastro mínimo`**

```go Cadastro mínimo
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://landing-zone-api.nilo.services/fhir/resources/Patient"

	payload := strings.NewReader("{\n  \"identifier\": [\n    {\n      \"system\": \"https://servicos.receita.fazenda.gov.br/servicos/cpf/\",\n      \"value\": \"39053344705\",\n      \"use\": \"official\"\n    },\n    {\n      \"system\": \"https://www.acmesaude.com.br/integracao/paciente/\",\n      \"value\": \"507823709\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"resourceType\": \"Patient\",\n  \"extension\": [\n    {\n      \"url\": \"https://landing-zone-api.nilo.services/fhir/resources/Group\",\n      \"valueIdentifier\": {\n        \"system\": \"https://www.acmesaude.com.br/integracao/grupo/\",\n        \"use\": \"usual\",\n        \"value\": \"diabeticos-tipo-2\"\n      }\n    },\n    {\n      \"url\": \"https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-sendWelcomingMessage\",\n      \"valueBoolean\": true\n    },\n    {\n      \"url\": \"https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-createOnboardingScheduling\",\n      \"valueBoolean\": true\n    }\n  ],\n  \"name\": [\n    {\n      \"family\": \"Silveira\",\n      \"given\": [\n        \"João\"\n      ],\n      \"use\": \"official\"\n    }\n  ]\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("x-api-key", "<apiKey>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`Cadastro mínimo`**

```ruby Cadastro mínimo
require 'uri'
require 'net/http'

url = URI("https://landing-zone-api.nilo.services/fhir/resources/Patient")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<apiKey>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"identifier\": [\n    {\n      \"system\": \"https://servicos.receita.fazenda.gov.br/servicos/cpf/\",\n      \"value\": \"39053344705\",\n      \"use\": \"official\"\n    },\n    {\n      \"system\": \"https://www.acmesaude.com.br/integracao/paciente/\",\n      \"value\": \"507823709\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"resourceType\": \"Patient\",\n  \"extension\": [\n    {\n      \"url\": \"https://landing-zone-api.nilo.services/fhir/resources/Group\",\n      \"valueIdentifier\": {\n        \"system\": \"https://www.acmesaude.com.br/integracao/grupo/\",\n        \"use\": \"usual\",\n        \"value\": \"diabeticos-tipo-2\"\n      }\n    },\n    {\n      \"url\": \"https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-sendWelcomingMessage\",\n      \"valueBoolean\": true\n    },\n    {\n      \"url\": \"https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-createOnboardingScheduling\",\n      \"valueBoolean\": true\n    }\n  ],\n  \"name\": [\n    {\n      \"family\": \"Silveira\",\n      \"given\": [\n        \"João\"\n      ],\n      \"use\": \"official\"\n    }\n  ]\n}"

response = http.request(request)
puts response.read_body
```

**`Cadastro mínimo`**

```java Cadastro mínimo
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://landing-zone-api.nilo.services/fhir/resources/Patient")
  .header("x-api-key", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{\n  \"identifier\": [\n    {\n      \"system\": \"https://servicos.receita.fazenda.gov.br/servicos/cpf/\",\n      \"value\": \"39053344705\",\n      \"use\": \"official\"\n    },\n    {\n      \"system\": \"https://www.acmesaude.com.br/integracao/paciente/\",\n      \"value\": \"507823709\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"resourceType\": \"Patient\",\n  \"extension\": [\n    {\n      \"url\": \"https://landing-zone-api.nilo.services/fhir/resources/Group\",\n      \"valueIdentifier\": {\n        \"system\": \"https://www.acmesaude.com.br/integracao/grupo/\",\n        \"use\": \"usual\",\n        \"value\": \"diabeticos-tipo-2\"\n      }\n    },\n    {\n      \"url\": \"https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-sendWelcomingMessage\",\n      \"valueBoolean\": true\n    },\n    {\n      \"url\": \"https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-createOnboardingScheduling\",\n      \"valueBoolean\": true\n    }\n  ],\n  \"name\": [\n    {\n      \"family\": \"Silveira\",\n      \"given\": [\n        \"João\"\n      ],\n      \"use\": \"official\"\n    }\n  ]\n}")
  .asString();
```

**`Cadastro mínimo`**

```php Cadastro mínimo
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://landing-zone-api.nilo.services/fhir/resources/Patient', [
  'body' => '{
  "identifier": [
    {
      "system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
      "value": "39053344705",
      "use": "official"
    },
    {
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709",
      "use": "usual"
    }
  ],
  "resourceType": "Patient",
  "extension": [
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/Group",
      "valueIdentifier": {
        "system": "https://www.acmesaude.com.br/integracao/grupo/",
        "use": "usual",
        "value": "diabeticos-tipo-2"
      }
    },
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-sendWelcomingMessage",
      "valueBoolean": true
    },
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-createOnboardingScheduling",
      "valueBoolean": true
    }
  ],
  "name": [
    {
      "family": "Silveira",
      "given": [
        "João"
      ],
      "use": "official"
    }
  ]
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'x-api-key' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

**`Cadastro mínimo`**

```csharp Cadastro mínimo
using RestSharp;

var client = new RestClient("https://landing-zone-api.nilo.services/fhir/resources/Patient");
var request = new RestRequest(Method.POST);
request.AddHeader("x-api-key", "<apiKey>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"identifier\": [\n    {\n      \"system\": \"https://servicos.receita.fazenda.gov.br/servicos/cpf/\",\n      \"value\": \"39053344705\",\n      \"use\": \"official\"\n    },\n    {\n      \"system\": \"https://www.acmesaude.com.br/integracao/paciente/\",\n      \"value\": \"507823709\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"resourceType\": \"Patient\",\n  \"extension\": [\n    {\n      \"url\": \"https://landing-zone-api.nilo.services/fhir/resources/Group\",\n      \"valueIdentifier\": {\n        \"system\": \"https://www.acmesaude.com.br/integracao/grupo/\",\n        \"use\": \"usual\",\n        \"value\": \"diabeticos-tipo-2\"\n      }\n    },\n    {\n      \"url\": \"https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-sendWelcomingMessage\",\n      \"valueBoolean\": true\n    },\n    {\n      \"url\": \"https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-createOnboardingScheduling\",\n      \"valueBoolean\": true\n    }\n  ],\n  \"name\": [\n    {\n      \"family\": \"Silveira\",\n      \"given\": [\n        \"João\"\n      ],\n      \"use\": \"official\"\n    }\n  ]\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Cadastro mínimo`**

```swift Cadastro mínimo
import Foundation

let headers = [
  "x-api-key": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = [
  "identifier": [
    [
      "system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
      "value": "39053344705",
      "use": "official"
    ],
    [
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709",
      "use": "usual"
    ]
  ],
  "resourceType": "Patient",
  "extension": [
    [
      "url": "https://landing-zone-api.nilo.services/fhir/resources/Group",
      "valueIdentifier": [
        "system": "https://www.acmesaude.com.br/integracao/grupo/",
        "use": "usual",
        "value": "diabeticos-tipo-2"
      ]
    ],
    [
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-sendWelcomingMessage",
      "valueBoolean": true
    ],
    [
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-createOnboardingScheduling",
      "valueBoolean": true
    ]
  ],
  "name": [
    [
      "family": "Silveira",
      "given": ["João"],
      "use": "official"
    ]
  ]
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://landing-zone-api.nilo.services/fhir/resources/Patient")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

O `system` é o namespace do **seu** sistema e o `value` é a chave do paciente lá dentro.
Reenviar o mesmo payload não gera duplicata, o que torna seguro reprocessar uma carga.

> **Warning**
>
> Criar um paciente pode disparar uma mensagem de boas-vindas por WhatsApp e liberar o
> primeiro agendamento — comportamento controlado pelas extensões obrigatórias, que assumem
> o padrão da sua unidade quando você as omite. Antes da primeira carga em volume, confirme
> esses padrões. Veja [Efeitos colaterais](#efeitos-colaterais).

> **Warning**
>
> Trocar o `system` de um paciente já integrado faz a Nilo tratá-lo como um paciente novo.
> O histórico fica partido em dois registros e não há como juntá-los depois pela API.

Um cadastro mais completo aceita CPF, contato, endereço, unidade de cuidado e as
extensões Nilo:

**`Requisição — Cadastro completo`**

```json title="Requisição — Cadastro completo"
{
  "resourceType": "Patient",
  "active": true,
  "identifier": [
    {
      "use": "usual",
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709"
    },
    {
      "use": "official",
      "system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
      "value": "39053344705"
    }
  ],
  "name": [
    {
      "use": "official",
      "text": "João Pedro Silveira",
      "family": "Silveira",
      "given": [
        "João",
        "Pedro"
      ]
    },
    {
      "use": "usual",
      "text": "Joana Silveira"
    }
  ],
  "gender": "male",
  "birthDate": "1974-12-25",
  "maritalStatus": {
    "coding": [
      {
        "code": "M",
        "display": "Married",
        "system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus"
      }
    ]
  },
  "telecom": [
    {
      "system": "phone",
      "value": "5511987654321",
      "use": "mobile"
    },
    {
      "system": "email",
      "value": "joao.silveira@example.com",
      "use": "home"
    }
  ],
  "address": [
    {
      "use": "home",
      "type": "both",
      "line": [
        "Rua das Acácias",
        "120",
        "Apto 42"
      ],
      "district": "Pinheiros",
      "city": "São Paulo",
      "state": "São Paulo",
      "postalCode": "01415000",
      "country": "Brasil"
    }
  ],
  "managingOrganization": {
    "type": "Organization",
    "identifier": {
      "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/sorting-hat-api--care-unit",
      "use": "usual",
      "value": "4"
    }
  },
  "extension": [
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-isLead",
      "valueBoolean": false
    },
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-sendWelcomingMessage",
      "valueBoolean": true
    },
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-createOnboardingScheduling",
      "valueBoolean": true
    },
    {
      "url": "http://hl7.org/fhir/StructureDefinition/patient-genderIdentity",
      "valueCodeableConcept": {
        "coding": [
          {
            "code": "male",
            "display": "male",
            "system": "http://hl7.org/fhir/gender-identity"
          }
        ]
      }
    },
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-religion",
      "valueCodeableConcept": {
        "text": "Católica"
      }
    },
    {
      "url": "http://hl7.org/fhir/StructureDefinition/patient-cadavericDonor",
      "valueBoolean": true
    }
  ],
  "contained": [
    {
      "resourceType": "Group",
      "type": "person",
      "actual": true,
      "name": "Diabéticos tipo 2",
      "identifier": [
        {
          "use": "usual",
          "system": "https://www.acmesaude.com.br/integracao/grupo/",
          "value": "diabeticos-tipo-2"
        }
      ]
    }
  ]
}
```

A resposta devolve o recurso como ficou gravado:

### Response (200)

```json
{
  "identifier": [
    {
      "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/hippocrates-api--patient",
      "value": "48210",
      "use": "usual"
    },
    {
      "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--patient-v2-token",
      "value": "0f1c2d3e-4a5b-6c7d-8e9f-a0b1c2d3e4f5",
      "use": "usual"
    },
    {
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709",
      "use": "usual"
    },
    {
      "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--patient-v2",
      "value": "31502",
      "use": "usual"
    }
  ],
  "resourceType": "Patient",
  "active": true,
  "contained": [
    {
      "resourceType": "Group",
      "identifier": [
        {
          "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/sorting-hat-api--cohort",
          "value": "904",
          "use": "usual"
        },
        {
          "system": "https://www.acmesaude.com.br/integracao/grupo/",
          "value": "diabeticos-tipo-2",
          "use": "usual"
        }
      ],
      "type": "person",
      "actual": true,
      "name": "Diabéticos tipo 2"
    }
  ],
  "communication": [
    {
      "language": {
        "coding": [
          {
            "code": "pt-BR",
            "display": "Portuguese (Brazil)",
            "system": "urn:ietf:bcp:47"
          }
        ]
      },
      "preferred": true
    }
  ],
  "extension": [
    {
      "url": "http://hl7.org/fhir/StructureDefinition/patient-genderIdentity",
      "valueCodeableConcept": {
        "coding": [
          {
            "code": "non-disclose",
            "display": "does not wish to disclose",
            "system": "http://hl7.org/fhir/gender-identity"
          }
        ]
      }
    },
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-cohort",
      "valueIdentifier": {
        "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/sorting-hat-api--cohort",
        "use": "usual",
        "value": "904"
      }
    },
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-sendWelcomingMessage",
      "valueBoolean": true
    },
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-createOnboardingScheduling",
      "valueBoolean": true
    },
    {
      "extension": [
        {
          "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-paths-home",
          "valueUrl": "https://acme.nilocare.app/patients/48210"
        }
      ],
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-paths"
    }
  ],
  "gender": "other",
  "id": "ba200cfa-dae0-46cf-81a0-008e3f7414b4",
  "meta": {
    "lastUpdated": "2026-08-06T13:04:12.905000Z",
    "versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
  },
  "name": [
    {
      "family": "Silveira",
      "given": [
        "João"
      ],
      "text": "João Silveira",
      "use": "official"
    }
  ]
}
```

Guarde o `id`: é por ele que se faz a leitura direta do paciente.

Repare que a resposta traz mais identificadores do que você enviou. A Nilo devolve o seu
`identifier` junto com os dela — o id interno do paciente
(`…/NamingSystem/hippocrates-api--patient`), o token
(`…/NamingSystem/care-api--patient-v2-token`), o id legado
(`…/NamingSystem/care-api--patient-v2`) e o CPF, quando houver. Todos servem para buscar;
o seu continua sendo o único que você precisa guardar.

> **Note**
>
> A atualização é parcial. Campo ausente ou enviado como `null` **preserva** o valor atual —
> não existe, por esta rota, como apagar um dado já gravado. São três as exceções: o nome
> social, removido quando o `name` com `use: usual` vem com `period.end` preenchido; a lista
> de grupos, substituída por inteiro quando `contained` é enviado; e `gender`, que omitido
> grava `other` por cima do valor atual — veja [Sexo](#sexo).

## Buscar

### Request

GET [https://landing-zone-api.nilo.services/fhir/resources/Patient](https://landing-zone-api.nilo.services/fhir/resources/Patient)

**`Busca com resultados`**

```curl Busca com resultados
curl -G https://landing-zone-api.nilo.services/fhir/resources/Patient \
     -H "x-api-key: <apiKey>" \
     -d _count=50 \
     -d _lastUpdated=eq2013-01-14 \
     -d active=true \
     --data-urlencode address=Acácias \
     --data-urlencode "address-city=São Paulo" \
     -d address-country=Brasil \
     -d address-postalcode=01415000 \
     --data-urlencode "address-state=São Paulo" \
     -d address-use=home \
     -d birthdate=1974-12-25 \
     -d death-date=ge2024-01-01 \
     -d deceased=true \
     --data-urlencode email=joao.silveira@example.com \
     -d family=Silveira \
     -d gender=male \
     --data-urlencode given=João \
     --data-urlencode identifier=https://www.acmesaude.com.br/integracao/paciente/|507823709 \
     -d language=pt-BR \
     --data-urlencode "name=João Silveira" \
     --data-urlencode organization=Organization/6e6a1b40-1e2a-4f1e-9f0e-2b1c3d4e5f60 \
     -d phone=5511987654321 \
     -d phonetic=Silveyra \
     --data-urlencode telecom=phone|5511987654321
```

**`Busca com resultados`**

```python Busca com resultados
import requests

url = "https://landing-zone-api.nilo.services/fhir/resources/Patient"

querystring = {"_count":"50","_lastUpdated":"[\"eq2013-01-14\"]","active":"true","address":"Acácias","address-city":"São Paulo","address-country":"Brasil","address-postalcode":"01415000","address-state":"São Paulo","address-use":"home","birthdate":"[\"1974-12-25\"]","death-date":"[\"ge2024-01-01\"]","deceased":"true","email":"joao.silveira@example.com","family":"Silveira","gender":"male","given":"João","identifier":"https://www.acmesaude.com.br/integracao/paciente/|507823709","language":"pt-BR","name":"João Silveira","organization":"Organization/6e6a1b40-1e2a-4f1e-9f0e-2b1c3d4e5f60","phone":"5511987654321","phonetic":"Silveyra","telecom":"phone|5511987654321"}

headers = {"x-api-key": "<apiKey>"}

response = requests.get(url, headers=headers, params=querystring)

print(response.json())
```

**`Busca com resultados`**

```javascript Busca com resultados
const url = 'https://landing-zone-api.nilo.services/fhir/resources/Patient?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&address=Ac%C3%A1cias&address-city=S%C3%A3o+Paulo&address-country=Brasil&address-postalcode=01415000&address-state=S%C3%A3o+Paulo&address-use=home&birthdate=%5B%221974-12-25%22%5D&death-date=%5B%22ge2024-01-01%22%5D&deceased=true&email=joao.silveira%40example.com&family=Silveira&gender=male&given=Jo%C3%A3o&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709&language=pt-BR&name=Jo%C3%A3o+Silveira&organization=Organization%2F6e6a1b40-1e2a-4f1e-9f0e-2b1c3d4e5f60&phone=5511987654321&phonetic=Silveyra&telecom=phone%7C5511987654321';
const options = {method: 'GET', headers: {'x-api-key': '<apiKey>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

**`Busca com resultados`**

```go Busca com resultados
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://landing-zone-api.nilo.services/fhir/resources/Patient?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&address=Ac%C3%A1cias&address-city=S%C3%A3o+Paulo&address-country=Brasil&address-postalcode=01415000&address-state=S%C3%A3o+Paulo&address-use=home&birthdate=%5B%221974-12-25%22%5D&death-date=%5B%22ge2024-01-01%22%5D&deceased=true&email=joao.silveira%40example.com&family=Silveira&gender=male&given=Jo%C3%A3o&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709&language=pt-BR&name=Jo%C3%A3o+Silveira&organization=Organization%2F6e6a1b40-1e2a-4f1e-9f0e-2b1c3d4e5f60&phone=5511987654321&phonetic=Silveyra&telecom=phone%7C5511987654321"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("x-api-key", "<apiKey>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`Busca com resultados`**

```ruby Busca com resultados
require 'uri'
require 'net/http'

url = URI("https://landing-zone-api.nilo.services/fhir/resources/Patient?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&address=Ac%C3%A1cias&address-city=S%C3%A3o+Paulo&address-country=Brasil&address-postalcode=01415000&address-state=S%C3%A3o+Paulo&address-use=home&birthdate=%5B%221974-12-25%22%5D&death-date=%5B%22ge2024-01-01%22%5D&deceased=true&email=joao.silveira%40example.com&family=Silveira&gender=male&given=Jo%C3%A3o&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709&language=pt-BR&name=Jo%C3%A3o+Silveira&organization=Organization%2F6e6a1b40-1e2a-4f1e-9f0e-2b1c3d4e5f60&phone=5511987654321&phonetic=Silveyra&telecom=phone%7C5511987654321")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<apiKey>'

response = http.request(request)
puts response.read_body
```

**`Busca com resultados`**

```java Busca com resultados
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://landing-zone-api.nilo.services/fhir/resources/Patient?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&address=Ac%C3%A1cias&address-city=S%C3%A3o+Paulo&address-country=Brasil&address-postalcode=01415000&address-state=S%C3%A3o+Paulo&address-use=home&birthdate=%5B%221974-12-25%22%5D&death-date=%5B%22ge2024-01-01%22%5D&deceased=true&email=joao.silveira%40example.com&family=Silveira&gender=male&given=Jo%C3%A3o&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709&language=pt-BR&name=Jo%C3%A3o+Silveira&organization=Organization%2F6e6a1b40-1e2a-4f1e-9f0e-2b1c3d4e5f60&phone=5511987654321&phonetic=Silveyra&telecom=phone%7C5511987654321")
  .header("x-api-key", "<apiKey>")
  .asString();
```

**`Busca com resultados`**

```php Busca com resultados
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://landing-zone-api.nilo.services/fhir/resources/Patient?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&address=Ac%C3%A1cias&address-city=S%C3%A3o+Paulo&address-country=Brasil&address-postalcode=01415000&address-state=S%C3%A3o+Paulo&address-use=home&birthdate=%5B%221974-12-25%22%5D&death-date=%5B%22ge2024-01-01%22%5D&deceased=true&email=joao.silveira%40example.com&family=Silveira&gender=male&given=Jo%C3%A3o&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709&language=pt-BR&name=Jo%C3%A3o+Silveira&organization=Organization%2F6e6a1b40-1e2a-4f1e-9f0e-2b1c3d4e5f60&phone=5511987654321&phonetic=Silveyra&telecom=phone%7C5511987654321', [
  'headers' => [
    'x-api-key' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

**`Busca com resultados`**

```csharp Busca com resultados
using RestSharp;

var client = new RestClient("https://landing-zone-api.nilo.services/fhir/resources/Patient?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&address=Ac%C3%A1cias&address-city=S%C3%A3o+Paulo&address-country=Brasil&address-postalcode=01415000&address-state=S%C3%A3o+Paulo&address-use=home&birthdate=%5B%221974-12-25%22%5D&death-date=%5B%22ge2024-01-01%22%5D&deceased=true&email=joao.silveira%40example.com&family=Silveira&gender=male&given=Jo%C3%A3o&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709&language=pt-BR&name=Jo%C3%A3o+Silveira&organization=Organization%2F6e6a1b40-1e2a-4f1e-9f0e-2b1c3d4e5f60&phone=5511987654321&phonetic=Silveyra&telecom=phone%7C5511987654321");
var request = new RestRequest(Method.GET);
request.AddHeader("x-api-key", "<apiKey>");
IRestResponse response = client.Execute(request);
```

**`Busca com resultados`**

```swift Busca com resultados
import Foundation

let headers = ["x-api-key": "<apiKey>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://landing-zone-api.nilo.services/fhir/resources/Patient?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&address=Ac%C3%A1cias&address-city=S%C3%A3o+Paulo&address-country=Brasil&address-postalcode=01415000&address-state=S%C3%A3o+Paulo&address-use=home&birthdate=%5B%221974-12-25%22%5D&death-date=%5B%22ge2024-01-01%22%5D&deceased=true&email=joao.silveira%40example.com&family=Silveira&gender=male&given=Jo%C3%A3o&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709&language=pt-BR&name=Jo%C3%A3o+Silveira&organization=Organization%2F6e6a1b40-1e2a-4f1e-9f0e-2b1c3d4e5f60&phone=5511987654321&phonetic=Silveyra&telecom=phone%7C5511987654321")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

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

### Response (200)

```json
{
  "resourceType": "Bundle",
  "type": "searchset",
  "entry": [
    {
      "fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4",
      "resource": {
        "identifier": [
          {
            "system": "https://www.acmesaude.com.br/integracao/paciente/",
            "value": "507823709",
            "use": "usual"
          }
        ],
        "resourceType": "Patient",
        "active": true,
        "id": "ba200cfa-dae0-46cf-81a0-008e3f7414b4",
        "name": [
          {
            "family": "Silveira",
            "given": [
              "João"
            ],
            "use": "official"
          }
        ]
      },
      "search": {
        "mode": "match"
      }
    }
  ],
  "link": [
    {
      "relation": "next",
      "url": "https://landing-zone-api.nilo.services/fhir/resources/Patient?_page_token=Cjj3YopYuf"
    }
  ]
}
```

> **Note**
>
> 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 (200)

```json
{
  "resourceType": "Bundle",
  "type": "searchset",
  "entry": [],
  "link": []
}
```

### Parâmetros de busca suportados

| Nome                 | Tipo                                                       | Descrição                                             | Expressão                                                 |
| -------------------- | ---------------------------------------------------------- | ----------------------------------------------------- | --------------------------------------------------------- |
| `identifier`         | [token](https://hl7.org/fhir/R4/search.html#token)         | Identificador do paciente, em `system\|value`         | `Patient.identifier`                                      |
| `active`             | [token](https://hl7.org/fhir/R4/search.html#token)         | Se o cadastro está ativo                              | `Patient.active`                                          |
| `name`               | [string](https://hl7.org/fhir/R4/search.html#string)       | Qualquer parte de qualquer nome                       | `Patient.name`                                            |
| `family`             | [string](https://hl7.org/fhir/R4/search.html#string)       | Parte do sobrenome                                    | `Patient.name.family`                                     |
| `given`              | [string](https://hl7.org/fhir/R4/search.html#string)       | Parte do primeiro nome                                | `Patient.name.given`                                      |
| `phonetic`           | [string](https://hl7.org/fhir/R4/search.html#string)       | Nome por correspondência fonética                     | `Patient.name`                                            |
| `birthdate`          | [date](https://hl7.org/fhir/R4/search.html#date)           | Data de nascimento                                    | `Patient.birthDate`                                       |
| `gender`             | [token](https://hl7.org/fhir/R4/search.html#token)         | Sexo administrativo                                   | `Patient.gender`                                          |
| `telecom`            | [token](https://hl7.org/fhir/R4/search.html#token)         | Qualquer contato                                      | `Patient.telecom`                                         |
| `phone`              | [token](https://hl7.org/fhir/R4/search.html#token)         | Telefone de contato                                   | `Patient.telecom.where(system='phone')`                   |
| `email`              | [token](https://hl7.org/fhir/R4/search.html#token)         | E-mail de contato                                     | `Patient.telecom.where(system='email')`                   |
| `address`            | [string](https://hl7.org/fhir/R4/search.html#string)       | Qualquer campo do endereço                            | `Patient.address`                                         |
| `address-city`       | [string](https://hl7.org/fhir/R4/search.html#string)       | Cidade                                                | `Patient.address.city`                                    |
| `address-state`      | [string](https://hl7.org/fhir/R4/search.html#string)       | Estado                                                | `Patient.address.state`                                   |
| `address-postalcode` | [string](https://hl7.org/fhir/R4/search.html#string)       | CEP                                                   | `Patient.address.postalCode`                              |
| `address-country`    | [string](https://hl7.org/fhir/R4/search.html#string)       | País                                                  | `Patient.address.country`                                 |
| `address-use`        | [token](https://hl7.org/fhir/R4/search.html#token)         | Finalidade do endereço — a Nilo grava sempre `home`   | `Patient.address.use`                                     |
| `organization`       | [reference](https://hl7.org/fhir/R4/search.html#reference) | Unidade de cuidado, no formato `Organization/{id}` \* | `Patient.managingOrganization`                            |
| `death-date`         | [date](https://hl7.org/fhir/R4/search.html#date)           | Data do óbito                                         | `(Patient.deceased as dateTime)`                          |
| `deceased`           | [token](https://hl7.org/fhir/R4/search.html#token)         | Se está marcado como falecido                         | `Patient.deceased.exists() and Patient.deceased != false` |
| `language`           | [token](https://hl7.org/fhir/R4/search.html#token)         | Idioma — a Nilo grava sempre `pt-BR`                  | `Patient.communication.language`                          |

\* O `{id}` do filtro `organization` é o `id` da unidade no store FHIR, não o
identificador que você usa no seu sistema. Pegue-o do `managingOrganization.reference` de
um paciente já lido.

> **Note**
>
> Estado civil, grupos e as extensões Nilo **não** são filtráveis: o FHIR R4 não define
> search parameters para eles no `Patient`. E **não há caminho pelo outro lado**: o
> [grupo de pacientes](/guia/recursos/group) não carrega a lista de membros. Para
> saber quem está num grupo, percorra os pacientes e leia o `contained` de cada um.

A busca mais comum na prática é pelo identificador do seu próprio sistema, que usa a
sintaxe `system|value`:

```bash
curl --request GET \
  --url 'https://landing-zone-api.nilo.services/fhir/resources/Patient?identifier=https://www.acmesaude.com.br/integracao/paciente/|507823709' \
  --header 'x-api-key: SUA_API_KEY'
```

### Paginação e recorte por data

Além dos search parameters do `Patient`, a busca aceita três parâmetros de controle:

| Nome           | Descrição                                                                                                                            |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `_lastUpdated` | Recorta por data de última alteração, com os prefixos FHIR de comparação (`eq`, `ge`, `le`). Enviado duas vezes, delimita um período |
| `_count`       | Quantos recursos por página                                                                                                          |
| `_page_token`  | Seleciona a página seguinte                                                                                                          |

A resposta não traz contagem total. Para percorrer todas as páginas, siga o `link` com
`relation: next` até ele deixar de vir — a URL já embute o `_page_token` da página
seguinte, e é o único jeito confiável de paginar:

```json
"link": [
  {
    "relation": "next",
    "url": "https://landing-zone-api.nilo.services/fhir/resources/Patient?_page_token=Cjj3YopYuf"
  }
]
```

## Ler por ID

### Request

GET [https://landing-zone-api.nilo.services/fhir/resources/Patient/\{id}](https://landing-zone-api.nilo.services/fhir/resources/Patient/\{id})

**`Paciente encontrado`**

```curl Paciente encontrado
curl https://landing-zone-api.nilo.services/fhir/resources/Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4 \
     -H "x-api-key: <apiKey>"
```

**`Paciente encontrado`**

```python Paciente encontrado
import requests

url = "https://landing-zone-api.nilo.services/fhir/resources/Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4"

headers = {"x-api-key": "<apiKey>"}

response = requests.get(url, headers=headers)

print(response.json())
```

**`Paciente encontrado`**

```javascript Paciente encontrado
const url = 'https://landing-zone-api.nilo.services/fhir/resources/Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4';
const options = {method: 'GET', headers: {'x-api-key': '<apiKey>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

**`Paciente encontrado`**

```go Paciente encontrado
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://landing-zone-api.nilo.services/fhir/resources/Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("x-api-key", "<apiKey>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`Paciente encontrado`**

```ruby Paciente encontrado
require 'uri'
require 'net/http'

url = URI("https://landing-zone-api.nilo.services/fhir/resources/Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<apiKey>'

response = http.request(request)
puts response.read_body
```

**`Paciente encontrado`**

```java Paciente encontrado
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://landing-zone-api.nilo.services/fhir/resources/Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4")
  .header("x-api-key", "<apiKey>")
  .asString();
```

**`Paciente encontrado`**

```php Paciente encontrado
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://landing-zone-api.nilo.services/fhir/resources/Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4', [
  'headers' => [
    'x-api-key' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

**`Paciente encontrado`**

```csharp Paciente encontrado
using RestSharp;

var client = new RestClient("https://landing-zone-api.nilo.services/fhir/resources/Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4");
var request = new RestRequest(Method.GET);
request.AddHeader("x-api-key", "<apiKey>");
IRestResponse response = client.Execute(request);
```

**`Paciente encontrado`**

```swift Paciente encontrado
import Foundation

let headers = ["x-api-key": "<apiKey>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://landing-zone-api.nilo.services/fhir/resources/Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

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

> **Warning**
>
> A leitura por ID **não** devolve o recurso na raiz da resposta. Ela devolve uma entrada
> com a mesma forma das entradas de `Bundle.entry` — `fullUrl`, `resource` e `search` — e o
> paciente está em `resource`. É a diferença mais fácil de errar entre esta rota e a busca:
> a busca envolve as entradas num `Bundle`, esta devolve uma entrada solta, mas em nenhuma
> das duas o `Patient` está no topo.

### Response (200)

```json
{
  "fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4",
  "resource": {
    "identifier": [
      {
        "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/hippocrates-api--patient",
        "value": "48210",
        "use": "usual"
      },
      {
        "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--patient-v2-token",
        "value": "0f1c2d3e-4a5b-6c7d-8e9f-a0b1c2d3e4f5",
        "use": "usual"
      },
      {
        "system": "https://www.acmesaude.com.br/integracao/paciente/",
        "value": "507823709",
        "use": "usual"
      },
      {
        "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--patient-v2",
        "value": "31502",
        "use": "usual"
      }
    ],
    "resourceType": "Patient",
    "active": true,
    "birthDate": "1974-12-25",
    "contained": [
      {
        "resourceType": "Group",
        "identifier": [
          {
            "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/sorting-hat-api--cohort",
            "value": "904",
            "use": "usual"
          },
          {
            "system": "https://www.acmesaude.com.br/integracao/grupo/",
            "value": "diabeticos-tipo-2",
            "use": "usual"
          }
        ],
        "type": "person",
        "actual": true,
        "name": "Diabéticos tipo 2"
      }
    ],
    "communication": [
      {
        "language": {
          "coding": [
            {
              "code": "pt-BR",
              "display": "Portuguese (Brazil)",
              "system": "urn:ietf:bcp:47"
            }
          ]
        },
        "preferred": true
      }
    ],
    "extension": [
      {
        "url": "http://hl7.org/fhir/StructureDefinition/patient-genderIdentity",
        "valueCodeableConcept": {
          "coding": [
            {
              "code": "non-disclose",
              "display": "does not wish to disclose",
              "system": "http://hl7.org/fhir/gender-identity"
            }
          ]
        }
      },
      {
        "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-cohort",
        "valueIdentifier": {
          "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/sorting-hat-api--cohort",
          "use": "usual",
          "value": "904"
        }
      },
      {
        "extension": [
          {
            "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-paths-home",
            "valueUrl": "https://acme.nilocare.app/patients/48210"
          }
        ],
        "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/patient-paths"
      }
    ],
    "gender": "male",
    "id": "ba200cfa-dae0-46cf-81a0-008e3f7414b4",
    "meta": {
      "lastUpdated": "2026-08-06T13:04:12.905000Z",
      "versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
    },
    "name": [
      {
        "family": "Silveira",
        "given": [
          "João"
        ],
        "text": "João Silveira",
        "use": "official"
      }
    ]
  },
  "search": {
    "mode": "match"
  }
}
```

## Valores aceitos

### Sexo

`gender` segue os códigos administrativos do FHIR, mas só dois sobrevivem à gravação:

| Enviado            | Gravado  | No NiloCare |
| ------------------ | -------- | ----------- |
| `male`             | `male`   | Masculino   |
| `female`           | `female` | Feminino    |
| `other`, `unknown` | `other`  | —           |
| ausente            | `other`  | —           |

> **Warning**
>
> A última linha é a pegadinha: `gender` é o único campo do `Patient` que não segue a regra
> da atualização parcial. Omitido, ele não preserva o sexo atual — grava `other` por cima.
> Um payload de correção de endereço, ou o exemplo **Adicionar CPF** desta página, apaga o
> sexo do paciente se não trouxer `gender`.
>
> Leia o paciente antes de atualizá-lo e reenvie o `gender` que voltou. Na leitura ele nunca
> vem nulo, então não há caso em que você não tenha o valor para reenviar.

### Identidade de gênero

Para registrar identidade de gênero, use a extensão `patient-genderIdentity`, que tem
vocabulário próprio:

| Código               | No NiloCare   |
| -------------------- | ------------- |
| `male`               | Homem         |
| `female`             | Mulher        |
| `transgender-male`   | Homem Trans   |
| `transgender-female` | Mulher Trans  |
| `other`              | Outro         |
| `non-disclose`       | Não informado |

Num paciente novo, qualquer outro código — ou a ausência da extensão — é gravado como
`non-disclose`. Num paciente que já existe, o valor atual é preservado.

### Estado civil

`maritalStatus` reconhece quatro códigos de
[`v3-MaritalStatus`](http://terminology.hl7.org/CodeSystem/v3-MaritalStatus) e um de
`v3-NullFlavor`:

| Código | No NiloCare   |
| ------ | ------------- |
| `S`    | Solteiro(a)   |
| `M`    | Casado(a)     |
| `D`    | Divorciado(a) |
| `W`    | Viúvo(a)      |
| `UNK`  | Outro         |

Num paciente novo, qualquer outro código cai em `UNK`, e é `UNK` que volta na leitura.
Num paciente que já existe, um código não reconhecido preserva o estado civil atual em vez
de sobrescrevê-lo.

## Efeitos colaterais

Uma escrita de `Patient` faz mais do que gravar o cadastro.

> **Warning**
>
> `patient-sendWelcomingMessage` com `valueBoolean: true` **envia uma mensagem de WhatsApp**
> ao paciente no momento do cadastro. Numa carga inicial de milhares de pacientes, isso são
> milhares de mensagens. A extensão é obrigatória, mas assume o padrão da sua unidade quando
> omitida — não deixe esse padrão decidir por você numa migração.

> **Warning**
>
> `patient-createOnboardingScheduling` com `valueBoolean: true` **libera o paciente para
> agendar** o primeiro atendimento assim que o cadastro entra. Vale a mesma cautela.

> **Note**
>
> Enviar `address` cria ou atualiza o endereço do paciente como registro próprio. Só o
> primeiro item de `address` é lido; os demais são descartados sem aviso.

> **Warning**
>
> `address.line` é posicional na escrita — `line[0]` logradouro, `line[1]` número,
> `line[2]` complemento — mas a leitura **omite** os itens vazios em vez de devolvê-los como
> string vazia. Num paciente sem logradouro, o número volta em `line[0]`; reenviar essa
> resposta sem tratar grava o número como logradouro. Ao montar uma escrita a partir de uma
> leitura, remonte `line` pelos rótulos, não pela posição em que veio.

> **Note**
>
> Enviar `contained` **substitui** a lista de grupos do paciente pela lista enviada — não
> acrescenta. Para adicionar um grupo, reenvie os que o paciente já tem mais o novo; para
> removê-lo, reenvie a lista sem ele. Veja [Grupos](#grupos).

## Regras de escrita e validações

Recusa é sempre `400` com um `OperationOutcome`: `issue[].expression` aponta o campo
culpado e `issue[].details.text` explica o motivo.

**`Resposta 400 — CPF inválido`**

```json title="Resposta 400 — CPF inválido"
{
  "resourceType": "OperationOutcome",
  "issue": [
    {
      "severity": "error",
      "code": "structure",
      "expression": [
        "Patient.identifier"
      ],
      "details": {
        "text": "Invalid CPF: must contain exactly 11 digits with no dots, commas or other characters."
      }
    }
  ]
}
```

> **Warning**
>
> Um payload que contenha a URL de **outro ambiente** da Nilo é recusado — a mensagem fala
> de "identifier from a Nilo environment that is not the current environment". Como as URLs
> das extensões Nilo e os `system` dos identificadores internos embutem o host do ambiente,
> é o erro esperado de quem copia um payload lido em produção e o reenvia em homologação.
> Ao migrar um exemplo entre ambientes, troque o host em todas as URLs, ou remova os
> identificadores e extensões que a Nilo devolveu e mande apenas os seus.

### O que depende da implantação

Três decisões são configuradas por unidade de cuidado no momento da implantação, e mudam
o que a API exige de você. Se não souber como a sua está, fale com o time antes de montar
a carga.

| Configuração                                    | Efeito                                                                                                   |
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| Namespaces de identificador                     | Define quais `system` são aceitos para encontrar um paciente já cadastrado, e em que ordem de prioridade |
| Unidade de cuidado padrão                       | Usada quando o payload não traz `managingOrganization` e o paciente ainda não existe                     |
| Grupo, boas-vindas e agendamento inicial padrão | Preenchem o que o payload omitir                                                                         |

### Identificadores

Ao menos um `identifier` é obrigatório, e o `system` enviado precisa estar entre os
namespaces habilitados para a sua unidade — é por ele que a Nilo decide entre criar e
atualizar. Enviar só identificadores de `system` desconhecido é recusado, em vez de
criar um paciente duplicado:

**`Resposta 400 — Nenhum identificador utilizável`**

```json title="Resposta 400 — Nenhum identificador utilizável"
{
  "resourceType": "OperationOutcome",
  "issue": [
    {
      "severity": "error",
      "code": "business-rule",
      "expression": [
        "Patient.identifier"
      ],
      "details": {
        "text": "Unable to use any of the provided identifiers to match an existing resource, which can lead to duplicates."
      }
    }
  ]
}
```

### CPF como identificador único

Por padrão, o `system` do CPF é o **identificador único** do paciente. É essa configuração
que torna o CPF obrigatório no cadastro: enquanto ela vale, um payload sem CPF não tem por
onde ser reconhecido e é recusado com o mesmo `OperationOutcome` da seção anterior — mesmo
que traga o identificador do seu próprio sistema.

> **Warning**
>
> Enquanto o CPF for o identificador único da sua implantação, **não há como cadastrar um
> paciente sem CPF** por esta API.

Nem toda operação tem o CPF de todo paciente. Se a sua precisa cadastrar sem ele — usando
o identificador do seu sistema como chave —, essa configuração pode ser trocada, mas não
pela API: **abra um ticket no Suporte** pedindo a mudança do identificador único da sua
unidade de cuidado.

Depois da troca, o CPF passa a ser opcional e continua aceito como identificador
adicional, com as mesmas regras de formato e de `use` descritas abaixo.

### CPF

O CPF é um `identifier` como os outros, mas com tratamento próprio: use o `system`
`https://servicos.receita.fazenda.gov.br/servicos/cpf/` e envie exatamente 11 dígitos, sem
pontos nem traços.

Para acrescentá-lo a um paciente que já existe, mande o identificador que encontra o
paciente, o CPF e o `gender` atual do paciente:

**`Requisição — Adicionar CPF`**

```json title="Requisição — Adicionar CPF"
{
  "resourceType": "Patient",
  "identifier": [
    {
      "use": "usual",
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709"
    },
    {
      "use": "official",
      "system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
      "value": "39053344705"
    }
  ],
  "gender": "male"
}
```

Como a atualização é parcial, o resto do cadastro fica intacto — nome, grupo e as
extensões obrigatórias não precisam ser reenviados. O `gender` é a exceção: omiti-lo grava
`other` por cima do sexo do paciente, e por isso ele acompanha o payload mesmo não sendo o
dado que se quer mudar. Veja [Sexo](#sexo). O CPF volta na resposta como mais um
identificador:

**`Resposta 200 — Paciente com CPF`**

```json title="Resposta 200 — Paciente com CPF"
{
  "resourceType": "Patient",
  "id": "ba200cfa-dae0-46cf-81a0-008e3f7414b4",
  "meta": {
    "versionId": "MTc4NjA5NDU2MTMxMDAwMDM2Nw",
    "lastUpdated": "2026-08-07T09:22:41.310000Z"
  },
  "active": true,
  "identifier": [
    {
      "use": "usual",
      "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/hippocrates-api--patient",
      "value": "48210"
    },
    {
      "use": "official",
      "system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
      "value": "39053344705"
    },
    {
      "use": "usual",
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709"
    },
    {
      "use": "usual",
      "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--patient-v2",
      "value": "31502"
    }
  ],
  "name": [
    {
      "use": "official",
      "text": "João Silveira",
      "family": "Silveira",
      "given": [
        "João"
      ]
    }
  ],
  "gender": "male"
}
```

O `use: official` não é decorativo: é ele que autoriza escrever por cima de um CPF já
gravado. Um CPF com qualquer outro `use` só entra se o paciente ainda não tiver CPF nenhum —
é assim que se envia um dado de baixa confiança sem sobrescrever o que já foi verificado.
Se o payload trouxer mais de um identificador de CPF, apenas o primeiro utilizável é lido.

> **Note**
>
> Note que o exemplo acima manda o identificador do seu sistema **junto** com o CPF. O CPF
> sozinho só encontra o paciente se o `system` da Receita estiver entre os namespaces
> habilitados para a sua unidade de cuidado.

> **Warning**
>
> Quando o `system` do CPF está habilitado para a sua unidade, ele passa a ser também a
> chave externa do paciente no NiloCare, à frente do identificador do parceiro. Isso vale
> para pacientes já cadastrados: a chave externa deles é trocada na escrita seguinte.

### Nome

Um paciente novo precisa de um `name` com `use: official` que tenha `text`, `given` ou
`family`; a Nilo prefere o `text` e, na falta dele, junta `given` e `family`. Um `name`
com `use: usual` vira o nome social. Se o payload trouxer mais de um `name` do mesmo
`use`, vale o **último** da lista.

Para remover o nome social, reenvie o `name` com `use: usual` e um `period.end` — qualquer
data serve, é a presença do campo que apaga o valor:

**`Requisição — Remover nome social`**

```json title="Requisição — Remover nome social"
{
  "resourceType": "Patient",
  "identifier": [
    {
      "use": "usual",
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709"
    }
  ],
  "name": [
    {
      "use": "official",
      "text": "João Pedro Silveira",
      "family": "Silveira",
      "given": [
        "João",
        "Pedro"
      ]
    },
    {
      "use": "usual",
      "text": "Joana Silveira",
      "period": {
        "end": "2026-03-01"
      }
    }
  ]
}
```

### Datas

O FHIR aceita datas parciais que o NiloCare não representa. Uma `birthDate` enviada como
`2022-12` é completada para `2022-12-01` ao ser gravada. Envie a data completa quando você
a tiver, para que a leitura devolva o que você espera.

### Grupos

Todo paciente pertence a pelo menos um grupo. Há três formas de indicar isso, e elas não
se combinam:

| Forma                                                                   | Múltiplos grupos | Quando usar                                              |
| ----------------------------------------------------------------------- | ---------------- | -------------------------------------------------------- |
| `contained` com um ou mais `Group`                                      | sim              | **Recomendada.** A única que representa mais de um grupo |
| extensão `…/fhir/resources/Group`, com o identificador de um `Group`    | não              | Um grupo só, sem montar o recurso contido                |
| extensão `…/StructureDefinition/patient-cohort`, com o id Nilo do grupo | não              | **Legada.** Mantida por compatibilidade                  |

A URL completa de cada uma está em [Extensões](/guia/conceitos/extensoes).

> **Warning**
>
> O `Group` referenciado precisa **já existir** — cadastre-o antes de referenciá-lo aqui.
> Um identificador que não resolve recusa a escrita inteira, e mandar grupo em `contained`
> e em `extension` ao mesmo tempo também.

Enviar `contained` substitui a lista inteira de grupos do paciente. Para acrescentar um
grupo, reenvie os grupos que o paciente já tem junto com o novo:

**`Requisição — Atualizar grupos`**

```json title="Requisição — Atualizar grupos"
{
  "resourceType": "Patient",
  "identifier": [
    {
      "use": "usual",
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709"
    }
  ],
  "contained": [
    {
      "resourceType": "Group",
      "type": "person",
      "actual": true,
      "name": "Diabéticos tipo 2",
      "identifier": [
        {
          "use": "usual",
          "system": "https://www.acmesaude.com.br/integracao/grupo/",
          "value": "diabeticos-tipo-2"
        }
      ]
    },
    {
      "resourceType": "Group",
      "type": "person",
      "actual": true,
      "name": "Hipertensos",
      "identifier": [
        {
          "use": "usual",
          "system": "https://www.acmesaude.com.br/integracao/grupo/",
          "value": "hipertensos"
        }
      ]
    }
  ]
}
```

Para remover, reenvie a lista sem o grupo que sai. Omitir `contained` por completo
preserva os grupos atuais — não os apaga. E num paciente que já existe as duas extensões
de grupo não têm efeito: só a criação as considera.

Sem grupo em `contained`, sem extensão de grupo e sem grupo padrão configurado para a
unidade, a criação é recusada:

**`Resposta 400 — Grupo não informado`**

```json title="Resposta 400 — Grupo não informado"
{
  "resourceType": "OperationOutcome",
  "issue": [
    {
      "severity": "error",
      "code": "structure",
      "expression": [
        "Patient.extension,contained"
      ],
      "details": {
        "text": "Extension with url NiloStructureDefinition.PATIENT_GROUP is required when no contained Group resourceType is present, or contained with resourceType=Group is required when no extension is present."
      }
    }
  ]
}
```

> **Note**
>
> Na leitura, os grupos voltam de duas formas ao mesmo tempo: `contained` traz **todos** e a
> extensão `patient-cohort` traz apenas o **primeiro**. Leia os grupos do `contained`; a
> extensão está lá por compatibilidade e não representa o conjunto.

### Unidade de cuidado

`managingOrganization` precisa apontar para uma unidade já cadastrada. Omitindo o campo,
a Nilo mantém a unidade que o paciente já tem ou, para um paciente novo, usa a unidade
padrão do care provider. Sem unidade no payload e sem unidade padrão configurada, a
criação falha:

**`Resposta 400 — Unidade padrão não configurada`**

```json title="Resposta 400 — Unidade padrão não configurada"
{
  "resourceType": "OperationOutcome",
  "issue": [
    {
      "severity": "error",
      "code": "not-found",
      "expression": [
        "Patient.?"
      ],
      "details": {
        "text": "A default care unit isn't configured for the care provider."
      }
    }
  ]
}
```

> **Warning**
>
> Esta integração representa **uma** unidade de cuidado por paciente. Um paciente que esteja
> em mais de uma unidade no NiloCare não sincroniza: a leitura falha em vez de devolver a
> primeira, e o erro que chega é um `400` genérico, sem apontar a causa. Se a sua base tem
> pacientes em várias unidades, fale com o time antes de integrá-la.

### Telefone

O telefone passa por validação de elegibilidade para WhatsApp, e um número reprovado
recusa a escrita inteira. Números de baixa confiança devem ir com `use: old` ou
`use: temp`: nesse caso o número é apenas descartado, sem derrubar a requisição nem
sobrescrever um contato mais atual.

O `value` precisa trazer DDI + DDD + número, no formato E.164. Espaços, parênteses e
hífens são removidos antes da validação. O DDI nunca é presumido: um número sem ele é
lido como se os primeiros dígitos fossem o código do país.

| `value` enviado       | Resultado                                                             |
| --------------------- | --------------------------------------------------------------------- |
| `5511987654321`       | Aceito                                                                |
| `+55 (11) 98765-4321` | Aceito, lido como `+5511987654321`                                    |
| `551187654321`        | Aceito. Celular brasileiro sem o nono dígito: a Nilo o inclui         |
| `11987654321`         | **Recusado** — falta o `55`, mesmo sendo um celular brasileiro válido |

Com mais de um `telecom` de telefone, um `use: old` é ignorado quando existe outro número,
e o `use` que corresponde à tag de telefone verificado da sua implantação tem precedência
sobre os demais.

### Status

> **Note**
>
> Os status de paciente **não** são um vocabulário fixo: cada care provider tem os seus,
> definidos na implantação. Não há como descobri-los pela API — peça a lista ao time antes
> de usar a extensão `patient-status`.

`active` e a extensão `…/StructureDefinition/patient-status` descrevem a mesma coisa por
caminhos diferentes. Enviando os dois, eles precisam concordar: um `active: true` com um
status de categoria inativa (ou o contrário) é recusado. O id da extensão também precisa
existir entre os status do seu care provider.

Enviando só `active` num paciente novo, a Nilo escolhe o status padrão ativo ou inativo da
unidade. Num paciente que já existe, o status atual é mantido quando concorda com o
`active` enviado, e trocado pelo padrão da categoria apenas quando discorda — um
`active: false` num paciente ativo o move para o status inativo padrão, sem escolher entre
os vários status inativos que o seu care provider possa ter.

Enviando nenhum dos dois, um paciente novo nasce com o status padrão ativo e um paciente
existente mantém o que já tinha.

### Campos ignorados

`communication` é sempre gravado como `pt-BR`, independentemente do que for enviado. A
extensão `…/StructureDefinition/patient-paths` é apenas devolvida — é o atalho para a
ficha do paciente no NiloCare. Extensões fora do contexto Nilo não têm efeito no cadastro,
mas ficam gravadas no recurso e voltam nas leituras seguintes — veja
[Extensões](/guia/conceitos/extensoes).

> **Note**
>
> Este endpoint não remove pacientes: a escrita nunca responde `204`. A remoção acontece do
> lado Nilo e é propagada para o store FHIR pela sincronização, não por esta API.

## Erros

Toda recusa de escrita é `400`, inclusive o cadastro duplicado. O corpo é um
`OperationOutcome` em que `issue[].expression` aponta o campo culpado e
`issue[].details.text` explica o motivo.

| `code`          | `expression`                   | Mensagem                                                                                                                                                                                                                            | Quando                                                                                                                                                                                                 |
| --------------- | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `structure`     | `Patient.<campo>`              | mensagem da validação FHIR                                                                                                                                                                                                          | O payload não é um `Patient` válido: tipo errado, valor fora do vocabulário, data malformada. Recusado antes de qualquer regra Nilo                                                                    |
| `structure`     | —                              | `Resource has identifier from a Nilo environment that is not the current environment.`                                                                                                                                              | O payload traz URLs da Nilo de outro ambiente. Também recusado antes do processamento, e por isso `expression` vem vazia                                                                               |
| `required`      | `Patient.identifier`           | `Field is required`                                                                                                                                                                                                                 | O payload não tem `identifier`                                                                                                                                                                         |
| `business-rule` | `Patient.identifier`           | `Unable to use any of the provided identifiers to match an existing resource, which can lead to duplicates.`                                                                                                                        | Há `identifier`, mas nenhum `system` habilitado para a sua unidade — não há como decidir entre criar e atualizar                                                                                       |
| `structure`     | `Patient.identifier`           | `Invalid CPF: must contain exactly 11 digits with no dots, commas or other characters.`                                                                                                                                             | O CPF não tem exatamente 11 dígitos                                                                                                                                                                    |
| `required`      | `Patient.name`                 | `Field name is required`                                                                                                                                                                                                            | Paciente novo sem nenhum `name`                                                                                                                                                                        |
| `invalid`       | `Patient.name`                 | `Name field has no values in text, given or family`                                                                                                                                                                                 | Há `name`, mas nenhum com `use: official` que traga `text`, `given` ou `family` — e não há cadastro anterior de onde herdar o nome                                                                     |
| `invalid`       | `Patient.telecom`              | `Invalid phone number: …`, ou a mensagem crua da validação de WhatsApp: `{"errors":"Invalid phone number +…"}`, sem os dois-pontos e com o número já prefixado por `+`. Um DDI estranho nela (ex.: `+28…`) indica que faltou o `55` | O telefone não passou na validação de elegibilidade para WhatsApp e não veio com `use: old` nem `use: temp`                                                                                            |
| `not-found`     | `Patient.managingOrganization` | `The provided CareUnit could not be found.`                                                                                                                                                                                         | A unidade de cuidado enviada não existe                                                                                                                                                                |
| `not-found`     | `Patient.?`                    | `A default care unit isn't configured for the care provider.`                                                                                                                                                                       | Sem `managingOrganization`, paciente novo e sem unidade padrão configurada. `expression` sai como `Patient.?` porque a falha é da configuração, não de um campo do payload                             |
| `structure`     | `Patient.contained`            | `Group with identifiers (system\|value) … does not exists`                                                                                                                                                                          | Um `Group` de `contained` não está cadastrado                                                                                                                                                          |
| `structure`     | `Patient.extension`            | `The provided Group could not be found.`                                                                                                                                                                                            | O grupo indicado pela extensão não resolve                                                                                                                                                             |
| `structure`     | `Patient.extension,contained`  | `Group cannot be defined both in extension and contained.`                                                                                                                                                                          | Grupo enviado em `contained` **e** em extensão                                                                                                                                                         |
| `structure`     | `Patient.extension,contained`  | `Extension with url NiloStructureDefinition.PATIENT_GROUP is required when no contained Group resourceType is present, …`                                                                                                           | Paciente novo sem grupo em `contained`, sem extensão de grupo e sem grupo padrão configurado                                                                                                           |
| `required`      | `Patient.extension`            | `Extension with url …/patient-sendWelcomingMessage is required.`                                                                                                                                                                    | A extensão de boas-vindas não tem valor no payload nem valor a herdar                                                                                                                                  |
| `structure`     | `Patient.extension`            | `Extension with url …/patient-createOnboardingScheduling is required.`                                                                                                                                                              | Idem, para a extensão de agendamento inicial                                                                                                                                                           |
| `not-found`     | `Patient.extension`            | `Patient status … does not exist`                                                                                                                                                                                                   | O id da extensão `patient-status` não existe entre os status do seu care provider                                                                                                                      |
| `invalid`       | `Patient.extension`            | `The active field is as …, but in the extension it is passing a status with … category`                                                                                                                                             | `active` e a categoria do status enviado se contradizem                                                                                                                                                |
| `conflict`      | —                              | `Resource conflicts with other existing resource(s)`, com a razão em `issue[].diagnostics`                                                                                                                                          | O cadastro duplica um registro que já existe do lado da Nilo. Repetir a requisição sem mudar o payload devolve o mesmo erro                                                                            |
| `exception`     | —                              | `<Exceção>: <mensagem>`                                                                                                                                                                                                             | Falha não prevista. É o que chega quando o paciente já está em mais de uma unidade de cuidado e o payload omitiu `managingOrganization`, ou quando o `identifier` enviado casa com mais de um paciente |

> **Warning**
>
> A recusa característica deste recurso é a do telefone. Basta o payload trazer algum
> `telecom` com `system: phone` para a validação rodar — e, se nenhum número do payload for
> aproveitado, é o telefone **já gravado** que vai à validação. Um número antigo reprovado
> derruba a escrita de qualquer outro campo.

**`Resposta 400 — Telefone reprovado na validação`**

```json title="Resposta 400 — Telefone reprovado na validação"
{
  "resourceType": "OperationOutcome",
  "issue": [
    {
      "severity": "error",
      "code": "invalid",
      "expression": [
        "Patient.telecom"
      ],
      "details": {
        "text": "{\"errors\":\"Invalid phone number +21987654321\"}"
      }
    }
  ]
}
```

Aqui o cliente enviou `21987654321`, sem o `55`. O `+` foi prefixado ao número como veio, e
`+21…` não é um DDI válido. Reenviado como `5521987654321`, o número passa.

O `use: old` ou `use: temp` que dispensa a recusa é lido do **último** `telecom` de telefone
do payload, não necessariamente daquele cujo número foi validado. Com um telefone só dá no
mesmo; com vários, mande o número de baixa confiança por último.

> **Note**
>
> Duas extensões obrigatórias falham com `code` diferente pela mesma causa:
> `patient-sendWelcomingMessage` sai como `required` e `patient-createOnboardingScheduling`
> como `structure`. Trate as duas como campo obrigatório ausente; não use o `code` para
> distinguir a natureza do problema.
>
> Elas assumem, num paciente novo, o padrão configurado na unidade de cuidado e, num paciente
> que já existe, o valor que ele já tem. A recusa acontece quando não há nem um nem outro.

> **Note**
>
> A extensão `patient-isLead` **não** é obrigatória, apesar de o `OperationOutcome` das outras
> duas sugerir simetria. Omiti-la nunca recusa a escrita.

> **Warning**
>
> Um `400` com `code: exception` pode chegar **depois** de o paciente já ter sido gravado — a
> falha acontece na etapa seguinte à gravação. Repetir a requisição é seguro, porque a escrita
> é upsert, mas não presuma que nada foi criado: confirme com uma busca por `identifier`.

> **Note**
>
> A mensagem do grupo obrigatório traz um marcador interno no lugar da URL da extensão. A
> extensão a que ela se refere é `…/fhir/resources/Group` — veja
> [Extensões](/guia/conceitos/extensoes).

As recusas de **leitura** não são `OperationOutcome`:
`GET /fhir/resources/Patient/{id}` responde `404` com `{"detail": "Not found."}` quando não
existe paciente com aquele `id`, e a busca responde `400` com um objeto `{"errors": [ … ]}`
quando um parâmetro é inválido.

Os payloads completos de cada recusa estão na aba **Referência**, em
`POST /fhir/resources/Patient`.

## O que a integração não cobre

A ficha do paciente no NiloCare tem campos que **não têm representação no `Patient`** e
por isso não podem ser preenchidos nem lidos por esta API. Eles só existem pela interface:

* **Tipo sanguíneo** e **Deficiências**

* **Escolaridade**, **Profissão** e **Com quem mora**

* **Cor ou raça autodeclarada**

* **Detalhes pessoais relevantes** (texto livre)

* **Nome da mãe**

Enviar esses dados dentro de extensões próprias não os faz aparecer na ficha: a extensão é
gravada no recurso FHIR e devolvida nas leituras, mas o cadastro do paciente não a lê.

O plano de saúde do paciente não fica no `Patient` — é o recurso
[`Coverage`](/guia/recursos/coverage), gravado à parte e ligado ao paciente por
`beneficiary`.