> 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.

# Profissional

> Cadastrar, atualizar e buscar profissionais de saúde no padrão FHIR Practitioner, com registro em conselho, especialidades e acesso ao NiloCare.

O [`Practitioner`](https://hl7.org/fhir/R4/practitioner.html) é a pessoa que presta o
cuidado, direta ou indiretamente — médico, enfermeiro, nutricionista, recepcionista. É quem
assina um atendimento, aparece como responsável na linha do tempo do paciente e compõe a
equipe de cuidado.

Este recurso é a alternativa a pedir cadastro de profissional ao Suporte: pela API você
cadastra a pessoa, registra o conselho e as especialidades, vincula as unidades de cuidado
em que ela atua e — se quiser — **concede o acesso ao NiloCare**, tudo na mesma escrita.

> **Warning**
>
> Escrever um `Practitioner` pode criar um usuário com acesso ao NiloCare e aos pacientes das
> unidades de cuidado vinculadas. É o efeito colateral mais forte desta API. Antes da primeira
> carga, leia [Acesso ao NiloCare](#acesso-ao-nilocare) e
> [Efeitos colaterais](#efeitos-colaterais).

## Campos

A coluna **No NiloCare** traz o rótulo com que o dado aparece para a equipe. São rótulos,
não caminhos de navegação: 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 profissional. É por aqui que a API decide entre criar e atualizar, e é aqui que vão e-mail, CPF e registro em conselho | **CPF**, **Conselho** / **Número** / **UF**, **E-mail** |
| `name`                                  | **sim**, com `use: official`              | Nome do profissional. De `text`, ou de `given` + `family`                                                                        | **Nome completo**                                       |
| `telecom` `system: phone`               | não                                       | Telefone. Havendo mais de um, vale o último                                                                                      | **Telefone**                                            |
| `gender`                                | não                                       | Sexo registrado                                                                                                                  | **Gênero**                                              |
| `qualification[]`                       | não                                       | Especialidades, uma por item, pelo código CBO                                                                                    | **Especialidades**                                      |
| `qualification[].period.end`            | não                                       | Data no passado **encerra** aquela especialidade                                                                                 | —                                                       |
| `address` `use: work`                   | não                                       | Locais de atendimento do profissional                                                                                            | **Locais de atendimento**                               |
| `extension` `practitioner-organization` | não 1                                     | Unidade de cuidado em que o profissional atua. Repetível                                                                         | **Unidades**                                            |
| `extension` `practitioner-user`         | não                                       | Acesso ao NiloCare: cria ou remove o login                                                                                       | —                                                       |
| `extension` `practitioner-user-email`   | **sim**, se o acesso está sendo concedido | E-mail de login                                                                                                                  | **E-mail**                                              |
| `extension` `practitioner-user-active`  | não                                       | `true` concede o acesso, `false` remove                                                                                          | —                                                       |
| `active`                                | não                                       | Só resposta: a leitura devolve sempre `true`                                                                                     | —                                                       |
| `extension` `practitioner-legacy-type`  | não                                       | Só resposta: classificação interna derivada do cadastro                                                                          | —                                                       |

1 Não é obrigatória, mas alguma unidade de cuidado sempre é aplicada: sem a
extensão vale a **unidade padrão** da sua implantação, e se não houver unidade padrão
configurada a escrita é recusada.

As URLs completas das extensões estão em [Extensões](/guia/conceitos/extensoes) — nesta
página elas aparecem só pelo nome final.

### Campos do `Practitioner` que a Nilo não usa

O `Practitioner` canônico tem campos que esta integração não lê nem grava: `photo`,
`birthDate`, `communication` e o `qualification[].issuer`. Ficam fora da referência de
propósito. Enviá-los não é erro — o valor é gravado no recurso FHIR e volta nas leituras
seguintes —, mas nada no NiloCare passa a exibi-los.

A extensão `practitioner-user-password` também não tem efeito: a senha não é definida por
esta API. O profissional recebe o convite de acesso pelo e-mail de login.

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

### Request

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

**`Cadastro mínimo`**

```curl Cadastro mínimo
curl -X POST https://landing-zone-api.nilo.services/fhir/resources/Practitioner \
     -H "x-api-key: <apiKey>" \
     -H "Content-Type: application/json" \
     -d '{
  "identifier": [
    {
      "system": "https://www.acmesaude.com.br/integracao/profissional/",
      "value": "5032932",
      "use": "usual"
    }
  ],
  "name": [
    {
      "text": "Ana Ribeiro",
      "use": "official"
    }
  ],
  "resourceType": "Practitioner"
}'
```

**`Cadastro mínimo`**

```python Cadastro mínimo
import requests

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

payload = {
    "identifier": [
        {
            "system": "https://www.acmesaude.com.br/integracao/profissional/",
            "value": "5032932",
            "use": "usual"
        }
    ],
    "name": [
        {
            "text": "Ana Ribeiro",
            "use": "official"
        }
    ],
    "resourceType": "Practitioner"
}
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/Practitioner';
const options = {
  method: 'POST',
  headers: {'x-api-key': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"identifier":[{"system":"https://www.acmesaude.com.br/integracao/profissional/","value":"5032932","use":"usual"}],"name":[{"text":"Ana Ribeiro","use":"official"}],"resourceType":"Practitioner"}'
};

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/Practitioner"

	payload := strings.NewReader("{\n  \"identifier\": [\n    {\n      \"system\": \"https://www.acmesaude.com.br/integracao/profissional/\",\n      \"value\": \"5032932\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"name\": [\n    {\n      \"text\": \"Ana Ribeiro\",\n      \"use\": \"official\"\n    }\n  ],\n  \"resourceType\": \"Practitioner\"\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/Practitioner")

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://www.acmesaude.com.br/integracao/profissional/\",\n      \"value\": \"5032932\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"name\": [\n    {\n      \"text\": \"Ana Ribeiro\",\n      \"use\": \"official\"\n    }\n  ],\n  \"resourceType\": \"Practitioner\"\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/Practitioner")
  .header("x-api-key", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{\n  \"identifier\": [\n    {\n      \"system\": \"https://www.acmesaude.com.br/integracao/profissional/\",\n      \"value\": \"5032932\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"name\": [\n    {\n      \"text\": \"Ana Ribeiro\",\n      \"use\": \"official\"\n    }\n  ],\n  \"resourceType\": \"Practitioner\"\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/Practitioner', [
  'body' => '{
  "identifier": [
    {
      "system": "https://www.acmesaude.com.br/integracao/profissional/",
      "value": "5032932",
      "use": "usual"
    }
  ],
  "name": [
    {
      "text": "Ana Ribeiro",
      "use": "official"
    }
  ],
  "resourceType": "Practitioner"
}',
  '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/Practitioner");
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://www.acmesaude.com.br/integracao/profissional/\",\n      \"value\": \"5032932\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"name\": [\n    {\n      \"text\": \"Ana Ribeiro\",\n      \"use\": \"official\"\n    }\n  ],\n  \"resourceType\": \"Practitioner\"\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://www.acmesaude.com.br/integracao/profissional/",
      "value": "5032932",
      "use": "usual"
    ]
  ],
  "name": [
    [
      "text": "Ana Ribeiro",
      "use": "official"
    ]
  ],
  "resourceType": "Practitioner"
] as [String : Any]

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

let request = NSMutableURLRequest(url: NSURL(string: "https://landing-zone-api.nilo.services/fhir/resources/Practitioner")! 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()
```

A resposta devolve o recurso como ficou gravado:

### Response (200)

```json
{
  "identifier": [
    {
      "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/almanac-api--professional",
      "value": "77412",
      "use": "usual"
    },
    {
      "system": "urn:ietf:rfc:6530",
      "value": "ana.ribeiro@acmesaude.com.br",
      "use": "usual"
    },
    {
      "system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
      "value": "52998224725",
      "use": "official"
    },
    {
      "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/NiloClassCouncil/",
      "value": "CRM-SP-118234",
      "use": "official"
    },
    {
      "system": "https://www.acmesaude.com.br/integracao/profissional/",
      "value": "5032932",
      "use": "usual"
    }
  ],
  "name": [
    {
      "text": "Ana Ribeiro",
      "use": "official"
    }
  ],
  "resourceType": "Practitioner",
  "active": true,
  "address": [
    {
      "city": "São Paulo",
      "country": "BR",
      "district": "Bela Vista",
      "line": [
        "Av. Paulista",
        "1000",
        "Sala 502"
      ],
      "postalCode": "01310-100",
      "state": "SP",
      "text": "Av. Paulista, 1000, Sala 502 - Bela Vista, São Paulo - SP, BR, 01310-100",
      "type": "both",
      "use": "work"
    }
  ],
  "extension": [
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/practitioner-legacy-type",
      "valueString": "care_user"
    },
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/practitioner-organization",
      "valueIdentifier": {
        "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/sorting-hat-api--care-unit",
        "use": "usual",
        "value": "4"
      }
    }
  ],
  "gender": "female",
  "id": "1a9c7f52-64b8-4a3e-8d21-9f0b7c4e6d38",
  "meta": {
    "lastUpdated": "2026-08-12T18:22:41.118000Z",
    "versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
  },
  "qualification": [
    {
      "code": {
        "coding": [
          {
            "code": "31",
            "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/almanac-api--specialty"
          },
          {
            "code": "225130",
            "system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRCBO"
          }
        ],
        "text": "Medicina de Família e Comunidade"
      }
    }
  ],
  "telecom": [
    {
      "system": "phone",
      "use": "mobile",
      "value": "+5511987654321"
    }
  ]
}
```

Guarde o `id`: é por ele que se faz a leitura direta. A resposta traz também o identificador
Nilo do profissional (`…/NamingSystem/almanac-api--professional`) ao lado do seu — os dois
servem para buscar, e o seu continua sendo o único que você precisa guardar.

> **Warning**
>
> A atualização de profissional **substitui**, não complementa. Assim como no `Coverage` e
> diferente do `Patient`, um campo omitido **não** preserva o valor atual: omitir `telecom`
> apaga o telefone, omitir `gender` volta o cadastro para não informado, omitir o
> identificador de CPF ou de conselho desfaz o vínculo com aquele documento. Para mudar só o
> telefone, reenvie o payload inteiro com o telefone novo.
>
> A única exceção é o **e-mail**: omitido, o e-mail que já estava gravado é preservado.

### Identificadores

Ao menos um `identifier` é obrigatório, e o `system` enviado precisa estar entre os
namespaces habilitados para a sua unidade de cuidado — é por ele que a Nilo decide entre
criar e atualizar. Enviar só identificadores de `system` desconhecido é recusado, em vez de
criar um profissional duplicado — é a recusa mais comum na primeira integração, e o payload
dela está em [Erros](#erros).

A mensagem lista os `system` que estão habilitados. Habilitar um novo não é feito pela API:
**abra um ticket no Suporte** informando a URI do seu namespace.

Além da chave do seu sistema, três `system` têm significado próprio:

| `system`                                                | O que carrega          |
| ------------------------------------------------------- | ---------------------- |
| `urn:ietf:rfc:6530`                                     | E-mail do profissional |
| `https://servicos.receita.fazenda.gov.br/servicos/cpf/` | CPF                    |
| `{host}/fhir/resources/NamingSystem/NiloClassCouncil/`  | Registro em conselho   |

> **Note**
>
> Estes três só servem para **encontrar** um profissional já cadastrado se também estiverem
> habilitados como namespaces de identificador da sua unidade. Não estando, eles continuam
> sendo gravados — CPF, conselho e e-mail entram no cadastro —, mas o casamento tem de vir de
> outro identificador.

### Registro em conselho

O registro vai num `identifier` no `system`
`{host}/fhir/resources/NamingSystem/NiloClassCouncil/`, e o `value` reúne num só campo os
três que o NiloCare mostra separados — **Conselho**, **UF** e **Número**:

```
conselho-UF-número
```

Por exemplo, `CRM-SP-118234`.

**`Requisição — Com CPF e registro no conselho`**

```json title="Requisição — Com CPF e registro no conselho"
{
  "resourceType": "Practitioner",
  "identifier": [
    {
      "use": "usual",
      "system": "https://www.acmesaude.com.br/integracao/profissional/",
      "value": "5032932"
    },
    {
      "use": "official",
      "system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
      "value": "52998224725"
    },
    {
      "use": "official",
      "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/NiloClassCouncil/",
      "value": "CRM-SP-118234"
    }
  ],
  "name": [
    {
      "use": "official",
      "given": [
        "Ana"
      ],
      "family": "Ribeiro"
    }
  ],
  "gender": "female",
  "telecom": [
    {
      "system": "phone",
      "value": "+5511987654321"
    }
  ]
}
```

> **Warning**
>
> O formato tem de ter **exatamente dois hifens**. Um número de registro que contenha hifen
> (`CRM-SP-1182-34`) é recusado, e o mesmo vale para um valor sem a UF (`CRM-118234`). Se o seu
> sistema guarda o registro num campo único com hifens, normalize antes de enviar.

A recusa vem com `code: invalid` apontando `Practitioner.identifier`. Os conselhos
reconhecidos estão em [Conselhos aceitos](#conselhos-aceitos).

### Acesso ao NiloCare

Quem controla o login é a extensão composta `practitioner-user`. **Sem ela, nada acontece
com o acesso** — o profissional é apenas um cadastro, e o login que ele já tivesse continua
como está.

Enviando a extensão, o que decide é `practitioner-user-active`:

| `practitioner-user-active` | Efeito                                                                                                |
| -------------------------- | ----------------------------------------------------------------------------------------------------- |
| `true`                     | Cria o usuário se ainda não existir, atualiza o nome dele e **concede o acesso** ao seu care provider |
| `false`                    | **Remove o acesso** do usuário ao seu care provider. O cadastro do profissional permanece             |
| ausente                    | Nada é feito com o acesso                                                                             |

**`Requisição — Com acesso ao NiloCare`**

```json title="Requisição — Com acesso ao NiloCare"
{
  "resourceType": "Practitioner",
  "identifier": [
    {
      "use": "usual",
      "system": "https://www.acmesaude.com.br/integracao/profissional/",
      "value": "5032932"
    },
    {
      "use": "usual",
      "system": "urn:ietf:rfc:6530",
      "value": "ana.ribeiro@acmesaude.com.br"
    }
  ],
  "name": [
    {
      "use": "official",
      "text": "Ana Ribeiro"
    }
  ],
  "extension": [
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/practitioner-user",
      "extension": [
        {
          "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/practitioner-user-active",
          "valueBoolean": true
        },
        {
          "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/practitioner-user-email",
          "valueString": "ana.ribeiro@acmesaude.com.br"
        }
      ]
    }
  ]
}
```

`practitioner-user-email` é **obrigatória quando o acesso está sendo concedido**: é o e-mail
com que o profissional entra na plataforma.

Sem ela, a recusa é `code: required` apontando `Practitioner.extension`.

Na remoção o e-mail também é necessário — é por ele que o usuário é localizado:

**`Requisição — Removendo o acesso ao NiloCare`**

```json title="Requisição — Removendo o acesso ao NiloCare"
{
  "resourceType": "Practitioner",
  "identifier": [
    {
      "use": "usual",
      "system": "https://www.acmesaude.com.br/integracao/profissional/",
      "value": "5032932"
    }
  ],
  "name": [
    {
      "use": "official",
      "text": "Ana Ribeiro"
    }
  ],
  "extension": [
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/practitioner-user",
      "extension": [
        {
          "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/practitioner-user-active",
          "valueBoolean": false
        },
        {
          "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/practitioner-user-email",
          "valueString": "ana.ribeiro@acmesaude.com.br"
        }
      ]
    }
  ]
}
```

> **Warning**
>
> `active: false` remove o acesso, não o cadastro. O profissional continua existindo, continua
> aparecendo em atendimentos passados e volta a ter acesso se você reenviar a extensão com
> `true`. Para o e-mail que não corresponde a nenhum usuário, `false` não é erro: nada é feito.

> **Note**
>
> O e-mail pode vir na extensão, no `identifier` do `system` `urn:ietf:rfc:6530`, ou nos dois.
> Nos dois, os valores **precisam ser iguais**. Basta haver um e-mail em qualquer um dos dois
> lugares para o profissional passar a ser tratado como usuário da plataforma — mas conceder o
> acesso exige o e-mail especificamente na **extensão**.

### Unidades de cuidado

Cada extensão `practitioner-organization` vincula o profissional a uma unidade de cuidado, e
com ela ao acesso aos pacientes daquela unidade. Uma extensão por unidade:

**`Requisição — Em várias unidades de cuidado`**

```json title="Requisição — Em várias unidades de cuidado"
{
  "resourceType": "Practitioner",
  "identifier": [
    {
      "use": "usual",
      "system": "https://www.acmesaude.com.br/integracao/profissional/",
      "value": "5032932"
    }
  ],
  "name": [
    {
      "use": "official",
      "text": "Ana Ribeiro"
    }
  ],
  "extension": [
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/practitioner-organization",
      "valueIdentifier": {
        "use": "usual",
        "system": "https://www.acmesaude.com.br/integracao/unidade-de-cuidado/",
        "value": "10654"
      }
    },
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/practitioner-organization",
      "valueIdentifier": {
        "use": "usual",
        "system": "https://www.acmesaude.com.br/integracao/unidade-de-cuidado/",
        "value": "9998232"
      }
    }
  ]
}
```

O `valueIdentifier` aceita **qualquer** identificador de uma unidade de cuidado já cadastrada,
inclusive o do seu próprio sistema. Para descobrir as unidades disponíveis, liste-as — veja
[Unidade de cuidado](/guia/recursos/organization):

### Request

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

**`Busca com resultados`**

```curl Busca com resultados
curl -G https://landing-zone-api.nilo.services/fhir/resources/Organization \
     -H "x-api-key: <apiKey>" \
     -d _count=50 \
     -d _lastUpdated=eq2013-01-14 \
     -d active=true \
     --data-urlencode identifier=https://www.acmesaude.com.br/integracao/unidade/|UC-01 \
     -d name=Centro
```

**`Busca com resultados`**

```python Busca com resultados
import requests

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

querystring = {"_count":"50","_lastUpdated":"[\"eq2013-01-14\"]","active":"true","identifier":"https://www.acmesaude.com.br/integracao/unidade/|UC-01","name":"Centro"}

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/Organization?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Funidade%2F%7CUC-01&name=Centro';
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/Organization?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Funidade%2F%7CUC-01&name=Centro"

	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/Organization?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Funidade%2F%7CUC-01&name=Centro")

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/Organization?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Funidade%2F%7CUC-01&name=Centro")
  .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/Organization?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Funidade%2F%7CUC-01&name=Centro', [
  '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/Organization?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Funidade%2F%7CUC-01&name=Centro");
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/Organization?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Funidade%2F%7CUC-01&name=Centro")! 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()
```

> **Warning**
>
> A semântica é de **adição**: a extensão nunca remove um vínculo. Um profissional vinculado a
> três unidades e reenviado com uma só continua nas três. Remover unidade de cuidado tem
> implicações de acesso a dados e é feito pelo **Suporte**, não pela API.

> **Note**
>
> Sem nenhuma extensão `practitioner-organization`, o profissional é vinculado à unidade de
> cuidado **padrão** da sua implantação. Não havendo unidade padrão configurada, a escrita é
> recusada.

> **Note**
>
> Quando o identificador enviado não resolve para nenhuma unidade cadastrada, o `expression`
> traz `Practitioner.extensions[0].valueIdentifier`, com um `s` a
> mais em `extension`. O índice é confiável — é a posição da extensão no seu payload —, mas o
> caminho não é um FHIRPath válido. Não o use como chave de tratamento automático.

### Especialidades

Cada especialidade é uma entrada de `qualification`, identificada pelo código **CBO** no
`system` `http://www.saude.gov.br/fhir/r4/CodeSystem/BRCBO`:

**`Requisição — Com especialidades`**

```json title="Requisição — Com especialidades"
{
  "resourceType": "Practitioner",
  "identifier": [
    {
      "use": "usual",
      "system": "https://www.acmesaude.com.br/integracao/profissional/",
      "value": "5032932"
    }
  ],
  "name": [
    {
      "use": "official",
      "text": "Ana Ribeiro"
    }
  ],
  "qualification": [
    {
      "code": {
        "coding": [
          {
            "system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRCBO",
            "code": "225130"
          }
        ]
      }
    },
    {
      "code": {
        "coding": [
          {
            "system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRCBO",
            "code": "225175"
          }
        ]
      }
    }
  ]
}
```

O CBO tem de existir no catálogo — se não existir, a recusa aponta o item e o `coding`
culpados em `Practitioner.qualification[N].code.coding[N].code`.

> **Warning**
>
> Para várias especialidades, use **uma entrada de `qualification` por especialidade**. Dois
> códigos CBO no mesmo `coding` que apontam para especialidades diferentes são recusados.

Todo item precisa de um `coding` no `system` do CBO — um item só com `text`, ou só com o
código do catálogo Nilo que vem nas leituras, é recusado.

Para **encerrar** uma especialidade, reenvie-a com `period.end` no passado:

**`Requisição — Encerrando uma especialidade`**

```json title="Requisição — Encerrando uma especialidade"
{
  "resourceType": "Practitioner",
  "identifier": [
    {
      "use": "usual",
      "system": "https://www.acmesaude.com.br/integracao/profissional/",
      "value": "5032932"
    }
  ],
  "name": [
    {
      "use": "official",
      "text": "Ana Ribeiro"
    }
  ],
  "qualification": [
    {
      "code": {
        "coding": [
          {
            "system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRCBO",
            "code": "225175"
          }
        ]
      },
      "period": {
        "end": "2026-07-31T23:59:00+00:00"
      }
    }
  ]
}
```

> **Note**
>
> `qualification` é aditivo: as especialidades já gravadas e ausentes do payload **continuam**.
> Só `period.end` remove. E `period` não volta na leitura — a resposta traz apenas as
> especialidades vigentes, cada uma com o CBO, o código do catálogo Nilo e o nome em `text`.

### Locais de atendimento

Endereços com `use: work` viram os locais de atendimento do profissional. O `line` é
posicional:

| Posição   | Conteúdo                      |
| --------- | ----------------------------- |
| `line[0]` | Logradouro                    |
| `line[1]` | Número — `S/N` quando ausente |
| `line[2]` | Complemento                   |

**`Requisição — Com local de atendimento`**

```json title="Requisição — Com local de atendimento"
{
  "resourceType": "Practitioner",
  "identifier": [
    {
      "use": "usual",
      "system": "https://www.acmesaude.com.br/integracao/profissional/",
      "value": "5032932"
    }
  ],
  "name": [
    {
      "use": "official",
      "text": "Ana Ribeiro"
    }
  ],
  "address": [
    {
      "use": "work",
      "line": [
        "Av. Paulista",
        "1000",
        "Sala 502"
      ],
      "district": "Bela Vista",
      "city": "São Paulo",
      "state": "SP",
      "country": "BR",
      "postalCode": "01310-100"
    }
  ]
}
```

> **Warning**
>
> Diferente das especialidades e das unidades, `address` **não** é aditivo: os locais de
> trabalho que estavam gravados e não vêm no payload são desvinculados do profissional. Envie
> sempre a lista completa dos locais em que ele atende.
>
> E o comportamento é instável quando o profissional já tem **mais de um** local gravado:
> nessa situação a sincronização pode criar um local duplicado e desvincular um que devia
> permanecer. Enquanto isso não estiver resolvido, prefira não enviar `address` em
> atualizações de profissional com vários locais — trate os locais pelo Suporte.

> **Note**
>
> Endereços com qualquer outro `use` são ignorados, sem erro. E a leitura devolve os locais com
> `use: work`, `type: both` e um `text` já formatado. `state` e `country` voltam como estão
> gravados; o `text` usa a **sigla** do estado e do país, que a Nilo guarda em campos separados
> e esta escrita não deriva. Ou seja: um local criado por aqui com `state: SP` volta com
> `state: SP`, e a sigla no `text` só aparece nos endereços que a plataforma normalizou.

## Buscar

### Request

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

**`Busca de profissionais com resultados`**

```curl Busca de profissionais com resultados
curl -G https://landing-zone-api.nilo.services/fhir/resources/Practitioner \
     -H "x-api-key: <apiKey>" \
     -d _lastUpdated=eq2013-01-14 \
     -d active=true \
     --data-urlencode "address-city=São Paulo" \
     -d address-postalcode=01310-100 \
     -d address-state=SP \
     -d gender=female \
     --data-urlencode identifier=https://www.acmesaude.com.br/integracao/profissional/|5032932 \
     --data-urlencode "name=Ana Ribeiro" \
     --data-urlencode phone=+5511987654321
```

**`Busca de profissionais com resultados`**

```python Busca de profissionais com resultados
import requests

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

querystring = {"_lastUpdated":"[\"eq2013-01-14\"]","active":"true","address-city":"São Paulo","address-postalcode":"01310-100","address-state":"SP","gender":"female","identifier":"https://www.acmesaude.com.br/integracao/profissional/|5032932","name":"Ana Ribeiro","phone":"+5511987654321"}

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

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

print(response.json())
```

**`Busca de profissionais com resultados`**

```javascript Busca de profissionais com resultados
const url = 'https://landing-zone-api.nilo.services/fhir/resources/Practitioner?_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&address-city=S%C3%A3o+Paulo&address-postalcode=01310-100&address-state=SP&gender=female&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fprofissional%2F%7C5032932&name=Ana+Ribeiro&phone=%2B5511987654321';
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 de profissionais com resultados`**

```go Busca de profissionais com resultados
package main

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

func main() {

	url := "https://landing-zone-api.nilo.services/fhir/resources/Practitioner?_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&address-city=S%C3%A3o+Paulo&address-postalcode=01310-100&address-state=SP&gender=female&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fprofissional%2F%7C5032932&name=Ana+Ribeiro&phone=%2B5511987654321"

	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 de profissionais com resultados`**

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

url = URI("https://landing-zone-api.nilo.services/fhir/resources/Practitioner?_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&address-city=S%C3%A3o+Paulo&address-postalcode=01310-100&address-state=SP&gender=female&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fprofissional%2F%7C5032932&name=Ana+Ribeiro&phone=%2B5511987654321")

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 de profissionais com resultados`**

```java Busca de profissionais 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/Practitioner?_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&address-city=S%C3%A3o+Paulo&address-postalcode=01310-100&address-state=SP&gender=female&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fprofissional%2F%7C5032932&name=Ana+Ribeiro&phone=%2B5511987654321")
  .header("x-api-key", "<apiKey>")
  .asString();
```

**`Busca de profissionais com resultados`**

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

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://landing-zone-api.nilo.services/fhir/resources/Practitioner?_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&address-city=S%C3%A3o+Paulo&address-postalcode=01310-100&address-state=SP&gender=female&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fprofissional%2F%7C5032932&name=Ana+Ribeiro&phone=%2B5511987654321', [
  'headers' => [
    'x-api-key' => '<apiKey>',
  ],
]);

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

**`Busca de profissionais com resultados`**

```csharp Busca de profissionais com resultados
using RestSharp;

var client = new RestClient("https://landing-zone-api.nilo.services/fhir/resources/Practitioner?_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&address-city=S%C3%A3o+Paulo&address-postalcode=01310-100&address-state=SP&gender=female&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fprofissional%2F%7C5032932&name=Ana+Ribeiro&phone=%2B5511987654321");
var request = new RestRequest(Method.GET);
request.AddHeader("x-api-key", "<apiKey>");
IRestResponse response = client.Execute(request);
```

**`Busca de profissionais com resultados`**

```swift Busca de profissionais com resultados
import Foundation

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

let request = NSMutableURLRequest(url: NSURL(string: "https://landing-zone-api.nilo.services/fhir/resources/Practitioner?_lastUpdated=%5B%22eq2013-01-14%22%5D&active=true&address-city=S%C3%A3o+Paulo&address-postalcode=01310-100&address-state=SP&gender=female&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fprofissional%2F%7C5032932&name=Ana+Ribeiro&phone=%2B5511987654321")! 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/Practitioner/1a9c7f52-64b8-4a3e-8d21-9f0b7c4e6d38",
      "resource": {
        "identifier": [
          {
            "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/almanac-api--professional",
            "value": "77412",
            "use": "usual"
          },
          {
            "system": "urn:ietf:rfc:6530",
            "value": "ana.ribeiro@acmesaude.com.br",
            "use": "usual"
          },
          {
            "system": "https://servicos.receita.fazenda.gov.br/servicos/cpf/",
            "value": "52998224725",
            "use": "official"
          },
          {
            "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/NiloClassCouncil/",
            "value": "CRM-SP-118234",
            "use": "official"
          },
          {
            "system": "https://www.acmesaude.com.br/integracao/profissional/",
            "value": "5032932",
            "use": "usual"
          }
        ],
        "name": [
          {
            "text": "Ana Ribeiro",
            "use": "official"
          }
        ],
        "resourceType": "Practitioner",
        "active": true,
        "extension": [
          {
            "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/practitioner-legacy-type",
            "valueString": "care_user"
          },
          {
            "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/practitioner-organization",
            "valueIdentifier": {
              "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/sorting-hat-api--care-unit",
              "use": "usual",
              "value": "4"
            }
          }
        ],
        "gender": "female",
        "id": "1a9c7f52-64b8-4a3e-8d21-9f0b7c4e6d38",
        "qualification": [
          {
            "code": {
              "coding": [
                {
                  "code": "31",
                  "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/almanac-api--specialty"
                },
                {
                  "code": "225130",
                  "system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRCBO"
                }
              ],
              "text": "Medicina de Família e Comunidade"
            }
          }
        ],
        "telecom": [
          {
            "system": "phone",
            "use": "mobile",
            "value": "+5511987654321"
          }
        ]
      },
      "search": {
        "mode": "match"
      }
    }
  ],
  "link": []
}
```

> **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 profissional, em `system\|value`. Vale para a sua chave, o e-mail, o CPF e o registro em conselho | `Practitioner.identifier`                    |
| `name`               | [string](https://hl7.org/fhir/R4/search.html#string) | Qualquer parte do nome                                                                                             | `Practitioner.name`                          |
| `phonetic`           | [string](https://hl7.org/fhir/R4/search.html#string) | Nome por correspondência fonética                                                                                  | `Practitioner.name`                          |
| `gender`             | [token](https://hl7.org/fhir/R4/search.html#token)   | Sexo registrado                                                                                                    | `Practitioner.gender`                        |
| `active`             | [token](https://hl7.org/fhir/R4/search.html#token)   | Se o cadastro está ativo — a Nilo grava sempre `true`                                                              | `Practitioner.active`                        |
| `phone`              | [token](https://hl7.org/fhir/R4/search.html#token)   | Telefone                                                                                                           | `Practitioner.telecom.where(system='phone')` |
| `telecom`            | [token](https://hl7.org/fhir/R4/search.html#token)   | Qualquer contato — na prática, o telefone                                                                          | `Practitioner.telecom`                       |
| `address`            | [string](https://hl7.org/fhir/R4/search.html#string) | Qualquer campo de um local de atendimento                                                                          | `Practitioner.address`                       |
| `address-city`       | [string](https://hl7.org/fhir/R4/search.html#string) | Cidade                                                                                                             | `Practitioner.address.city`                  |
| `address-state`      | [string](https://hl7.org/fhir/R4/search.html#string) | Estado                                                                                                             | `Practitioner.address.state`                 |
| `address-postalcode` | [string](https://hl7.org/fhir/R4/search.html#string) | CEP                                                                                                                | `Practitioner.address.postalCode`            |
| `address-country`    | [string](https://hl7.org/fhir/R4/search.html#string) | País                                                                                                               | `Practitioner.address.country`               |
| `address-use`        | [token](https://hl7.org/fhir/R4/search.html#token)   | Finalidade do endereço — a Nilo grava sempre `work`                                                                | `Practitioner.address.use`                   |

> **Warning**
>
> Dois parâmetros canônicos do `Practitioner` existem e **não encontram nada** aqui. `family` e
> `given` filtram partes do nome, e a Nilo grava o nome inteiro num único `name[0].text` — use
> `name`. E `email` filtra `telecom` com `system: email`, mas o e-mail do profissional não fica
> em `telecom`: fica em `identifier`, no `system` `urn:ietf:rfc:6530`. Para achar alguém pelo
> e-mail, use `identifier=urn:ietf:rfc:6530|ana.ribeiro@acmesaude.com.br`.

> **Note**
>
> Especialidade, unidade de cuidado e acesso ao NiloCare **não** são filtráveis: o FHIR R4 não
> define search parameter para `qualification` nem para extensões no `Practitioner`.

A busca mais comum na prática é pelo identificador do seu próprio sistema:

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

## Ler por ID

### Request

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

**`Profissional encontrado`**

```curl Profissional encontrado
curl https://landing-zone-api.nilo.services/fhir/resources/Practitioner/id \
     -H "x-api-key: <apiKey>"
```

**`Profissional encontrado`**

```python Profissional encontrado
import requests

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

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

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

print(response.json())
```

**`Profissional encontrado`**

```javascript Profissional encontrado
const url = 'https://landing-zone-api.nilo.services/fhir/resources/Practitioner/id';
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);
}
```

**`Profissional encontrado`**

```go Profissional encontrado
package main

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

func main() {

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

	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))

}
```

**`Profissional encontrado`**

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

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

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
```

**`Profissional encontrado`**

```java Profissional 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/Practitioner/id")
  .header("x-api-key", "<apiKey>")
  .asString();
```

**`Profissional encontrado`**

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

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://landing-zone-api.nilo.services/fhir/resources/Practitioner/id', [
  'headers' => [
    'x-api-key' => '<apiKey>',
  ],
]);

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

**`Profissional encontrado`**

```csharp Profissional encontrado
using RestSharp;

var client = new RestClient("https://landing-zone-api.nilo.services/fhir/resources/Practitioner/id");
var request = new RestRequest(Method.GET);
request.AddHeader("x-api-key", "<apiKey>");
IRestResponse response = client.Execute(request);
```

**`Profissional encontrado`**

```swift Profissional encontrado
import Foundation

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

let request = NSMutableURLRequest(url: NSURL(string: "https://landing-zone-api.nilo.services/fhir/resources/Practitioner/id")! 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()
```

Diferente da busca, a leitura por ID devolve o recurso direto, sem envelope `Bundle`, e
responde `404` quando o `id` não existe.

### Response (200)

```json
{
  "identifier": [
    {
      "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/almanac-api--professional",
      "value": "77412",
      "use": "usual"
    },
    {
      "system": "urn:ietf:rfc:6530",
      "value": "ana.ribeiro@acmesaude.com.br",
      "use": "usual"
    },
    {
      "system": "https://www.acmesaude.com.br/integracao/profissional/",
      "value": "5032932",
      "use": "usual"
    }
  ],
  "name": [
    {
      "text": "Ana Ribeiro",
      "use": "official"
    }
  ],
  "resourceType": "Practitioner",
  "active": true,
  "extension": [
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/practitioner-legacy-type",
      "valueString": "care_user"
    },
    {
      "url": "https://landing-zone-api.nilo.services/fhir/resources/StructureDefinition/practitioner-organization",
      "valueIdentifier": {
        "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/sorting-hat-api--care-unit",
        "use": "usual",
        "value": "4"
      }
    }
  ],
  "gender": "female",
  "id": "1a9c7f52-64b8-4a3e-8d21-9f0b7c4e6d38",
  "meta": {
    "lastUpdated": "2026-08-12T18:22:41.118000Z",
    "versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
  },
  "telecom": [
    {
      "system": "phone",
      "use": "mobile",
      "value": "+5511987654321"
    }
  ]
}
```

## Valores aceitos

### Conselhos aceitos

O `conselho` do registro é a sigla do conselho de classe. O NiloCare reconhece:

| Sigla     | Conselho                                                |
| --------- | ------------------------------------------------------- |
| `ABG`     | Associação Brasileira de Gerontologia                   |
| `CRM`     | Conselho Regional de Medicina                           |
| `CFM`     | Conselho Federal de Medicina                            |
| `COREN`   | Conselho Regional de Enfermagem                         |
| `COFEN`   | Conselho Federal de Enfermagem                          |
| `CRF`     | Conselho Regional de Farmácia                           |
| `CFF`     | Conselho Federal de Farmácia                            |
| `CRBM`    | Conselho Regional de Biomedicina                        |
| `CFBM`    | Conselho Federal de Biomedicina                         |
| `CREFITO` | Conselho Regional de Fisioterapia e Terapia Ocupacional |
| `COFFITO` | Conselho Federal de Fisioterapia                        |
| `CREFONO` | Conselho Regional de Fonoaudiologia                     |
| `CFFA`    | Conselho Federal de Fonoaudiologia                      |
| `CRN`     | Conselho Regional de Nutricionistas                     |
| `CFN`     | Conselho Federal de Nutricionistas                      |
| `CRP`     | Conselho Regional de Psicologia                         |
| `CFP`     | Conselho Federal de Psicologia                          |
| `CREF`    | Conselho Regional de Educação Física                    |
| `CONFEF`  | Conselho Federal de Educação Física                     |

A `UF` é a sigla de duas letras do estado que emitiu o registro.

### Gênero

`gender` usa os quatro códigos do FHIR R4:

| Código    | No NiloCare   |
| --------- | ------------- |
| `male`    | Masculino     |
| `female`  | Feminino      |
| `other`   | Outro         |
| `unknown` | Não informado |

Qualquer outro valor, ou a ausência do campo, é gravado como **não informado** e volta como
`unknown` na leitura.

### Especialidades

As especialidades não são um vocabulário fixo desta API: elas vêm do catálogo de
**CBO** (Classificação Brasileira de Ocupações) e do catálogo de especialidades do NiloCare,
que a implantação mantém. `225130` é Médico de Família e Comunidade, `225175` é Médico
Geneticista.

A leitura devolve, além do CBO que você enviou, o código do catálogo Nilo da especialidade e
o nome dela em `text` — é por esse nome que a especialidade aparece na plataforma.

## Efeitos colaterais

A escrita de `Practitioner` faz mais do que gravar o cadastro.

> **Warning**
>
> Com a extensão `practitioner-user` e `active: true`, a escrita **cria um usuário e concede
> acesso ao NiloCare** — e com ele o acesso aos pacientes de todas as unidades de cuidado
> vinculadas ao profissional. Com `active: false`, ela **remove** o acesso. Nos dois casos o
> efeito é imediato e não passa por aprovação.

> **Warning**
>
> Enviar `address` **desvincula** os locais de atendimento que não vierem no payload.

> **Note**
>
> CPF e registro em conselho que ainda não existiam são criados no cadastro da Nilo, e um CPF
> ou registro já cadastrado é reaproveitado em vez de duplicado.

> **Note**
>
> Este endpoint não remove profissionais: 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. O mesmo vale
> para o vínculo com unidade de cuidado, que a API só sabe adicionar.

## Erros

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

| `code`          | `expression`                                        | O que aconteceu                                                                           |
| --------------- | --------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `business-rule` | `Practitioner.identifier`                           | Nenhum `system` enviado está habilitado para a sua unidade. A mensagem lista os que estão |
| `invalid`       | `Practitioner.identifier`                           | Registro em conselho fora do formato `conselho-UF-número`                                 |
| `required`      | `Practitioner.identifier`                           | Nenhum `identifier` no payload                                                            |
| `required`      | `Practitioner.name`                                 | `name` ausente                                                                            |
| `required`      | `Practitioner.extension`                            | Acesso sendo concedido sem `practitioner-user-email`                                      |
| `business-rule` | —                                                   | E-mail do `identifier` e da extensão de login divergem                                    |
| `business-rule` | `Practitioner.qualification[N].code.coding`         | Item sem `coding` no `system` do CBO, ou com dois CBOs de especialidades diferentes       |
| `business-rule` | `Practitioner.qualification[N].code.coding[N].code` | CBO inexistente no catálogo                                                               |
| `not-found`     | `Practitioner.extensions[N].valueIdentifier`        | Unidade de cuidado da extensão não encontrada                                             |
| `not-found`     | `Practitioner.?`                                    | Sem extensão de unidade e sem unidade padrão configurada                                  |
| `exception`     | —                                                   | Os identificadores casaram com mais de um profissional                                    |
| `exception`     | —                                                   | Falha ao criar o usuário de acesso                                                        |

O erro que toda primeira integração encontra é o do identificador não habilitado:

**`Resposta 400 — Identificador não reconhecido`**

```json title="Resposta 400 — Identificador não reconhecido"
{
  "resourceType": "OperationOutcome",
  "issue": [
    {
      "severity": "error",
      "code": "business-rule",
      "expression": [
        "Practitioner.identifier"
      ],
      "details": {
        "text": "Unable to use any of the provided identifiers to match an existing resource, which can lead to duplicates. Configured identifier systems: https://www.acmesaude.com.br/integracao/profissional/, urn:ietf:rfc:6530."
      }
    }
  ]
}
```

> **Warning**
>
> Este erro só sai quando `name` está **ausente**. Um `name` presente mas sem nenhum item
> `use: official` passa pela validação e grava o profissional **sem nome** — a escrita responde
> `200` e o cadastro fica vazio no lugar do nome. Confira o `use` antes de montar a carga.

> **Note**
>
> Os dois últimos chegam da camada de execução sem serem reformulados, e por isso o `code` é o
> genérico `exception` e o `details.text` é técnico. Trate-os pela mensagem aproximada, não pelo
> texto exato — ele pode mudar.

> **Note**
>
> A aba **Referência** traz o payload de **todos** estes erros: abra o endpoint de cadastro do
> Profissional e troque o exemplo na resposta `400`.

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

Nem a senha nem a redefinição de senha do profissional são definidas por esta API: o convite
de acesso vai por e-mail. Perfil e permissões dentro do NiloCare também não — a API concede
ou remove o acesso, e o que a pessoa pode fazer depois é configuração da plataforma.

A remoção de vínculo com unidade de cuidado e a remoção do cadastro do profissional passam
pelo **Suporte**.

E a especialidade **por unidade** não existe aqui: `qualification` descreve as especialidades
da pessoa, não o que ela atende em cada unidade. O papel do profissional dentro de uma equipe
é assunto do `CareTeam`.