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

# Arquivo do paciente

> Enviar documentos PDF para a ficha de um paciente e consultar os arquivos dele, no padrão FHIR Media.

Um **arquivo do paciente** é um documento anexado à ficha dele: um laudo, um resultado de
exame, um relatório, um termo assinado. No Nilo Care esses arquivos ficam na aba
**Arquivos** da ficha do paciente — *Pacientes › \[nome do paciente] › Arquivos* —, onde a
equipe de cuidado os abre, baixa, renomeia e exclui.

No FHIR o recurso é o [`Media`](https://hl7.org/fhir/R4/media.html), e esta integração o usa
para as duas pontas: **enviar** um PDF e **consultar** o que o paciente tem.

> **Warning**
>
> **Este recurso não tem atualização.** Ao contrário de todos os outros, o mesmo `POST` não
> cria e atualiza: se o `identifier` que você mandar já corresponder a um arquivo existente, a
> chamada é **recusada**. Cada arquivo enviado precisa de uma chave nova.
>
> Também não há como apagar nem renomear um arquivo por esta API. Pela integração, só criar e
> consultar; excluir e renomear são ações da equipe no Nilo Care.

## Campos

A coluna **No Nilo Care** traz o rótulo com que o dado aparece para a equipe; são rótulos,
não caminhos de navegação.

| Campo                 | Obrigatório        | O que significa                                                                                                                                                           | No Nilo Care                                                  |
| --------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| `resourceType`        | **sim**            | Constante `Media`                                                                                                                                                         | —                                                             |
| `identifier`          | **sim**            | Suas chaves do arquivo. Precisa ser **nova a cada arquivo** — é por aqui que a API descobre que o arquivo já existe, e arquivo que já existe não é atualizado             | —                                                             |
| `status`              | **sim**            | Exigido pelo FHIR e sem efeito no cadastro. Envie `completed`, que é o valor que a leitura sempre devolve                                                                 | —                                                             |
| `subject`             | **sim**            | O paciente do arquivo, por um identificador dele. `type` é `Patient` — omitido, é assumido                                                                                | o arquivo aparece na aba **Arquivos** da ficha desse paciente |
| `content`             | **sim**            | O arquivo. Informe `url` **ou** `data`                                                                                                                                    | —                                                             |
| `content.url`         | um dos dois        | Na escrita, o endereço de onde a plataforma vai baixar o arquivo. Na leitura, o caminho interno de armazenamento — **não** um link de download                            | —                                                             |
| `content.data`        | um dos dois        | O PDF em base64, embutido na requisição. Nunca é devolvido na leitura                                                                                                     | —                                                             |
| `content.title`       | não                | Nome do arquivo. **Só é preservado no envio por `data`**. Não é estável: a equipe pode renomear o arquivo no Nilo Care, e o nome novo passa a ser o que a leitura devolve | o nome do arquivo na lista da aba **Arquivos**                |
| `content.contentType` | **sim** com `data` | Tipo do conteúdo. Só `application/pdf` é aceito. Não é guardado nem devolvido                                                                                             | —                                                             |
| `content.size`        | não                | Tamanho em bytes do conteúdo decodificado. Informado, tem de bater exatamente. Não é guardado nem devolvido                                                               | —                                                             |
| `id` · `meta`         | não                | Só resposta: identificador Nilo FHIR do arquivo e metadados da gravação                                                                                                   | —                                                             |

### Campos que a Nilo não usa

O `Media` canônico traz muito mais do que esta integração lê: `type`, `modality`, `view`,
`encounter`, `createdDateTime`, `issued`, `operator`, `reasonCode`, `bodySite`, `device`,
`height`, `width`, `duration`, `frames`, `note`, `partOf`, `basedOn` — e, dentro de
`content`, o `hash`. Nenhum deles é lido, e por isso nenhum aparece na referência do recurso.

> **Note**
>
> A referência não os declara, mas a API **não recusa** quem os manda — e nenhum deles tem
> efeito. O `content.hash`, em particular, passa e **não é conferido**: não conte com ele para
> validar a integridade do envio; use o `content.size`, que é conferido.
>
> Os campos de topo, no entanto, **ficam guardados no recurso** e voltam nas leituras
> seguintes. Se você mandar um `type` ou um `createdDateTime`, eles vão reaparecer nas suas
> consultas — e até responder a uma busca por aquele campo — sem nunca terem significado nada
> para a plataforma. Parece dado da Nilo, e não é. Omita-os.

## Enviar um arquivo

### Request

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

**`Enviar por URL`**

```curl Enviar por URL
curl -X POST https://landing-zone-api.nilo.services/fhir/resources/Media \
     -H "x-api-key: <apiKey>" \
     -H "Content-Type: application/json" \
     -d '{
  "resourceType": "Media",
  "identifier": [
    {
      "system": "https://www.acmesaude.com.br/integracao/arquivo/",
      "value": "77001",
      "use": "usual"
    }
  ],
  "status": "completed",
  "subject": {
    "identifier": {
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709",
      "use": "usual"
    },
    "type": "Patient"
  },
  "content": {
    "url": "https://arquivos.acmesaude.com.br/laudos/laudo-77001.pdf"
  }
}'
```

**`Enviar por URL`**

```python Enviar por URL
import requests

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

payload = {
    "resourceType": "Media",
    "identifier": [
        {
            "system": "https://www.acmesaude.com.br/integracao/arquivo/",
            "value": "77001",
            "use": "usual"
        }
    ],
    "status": "completed",
    "subject": {
        "identifier": {
            "system": "https://www.acmesaude.com.br/integracao/paciente/",
            "value": "507823709",
            "use": "usual"
        },
        "type": "Patient"
    },
    "content": { "url": "https://arquivos.acmesaude.com.br/laudos/laudo-77001.pdf" }
}
headers = {
    "x-api-key": "<apiKey>",
    "Content-Type": "application/json"
}

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

print(response.json())
```

**`Enviar por URL`**

```javascript Enviar por URL
const url = 'https://landing-zone-api.nilo.services/fhir/resources/Media';
const options = {
  method: 'POST',
  headers: {'x-api-key': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"resourceType":"Media","identifier":[{"system":"https://www.acmesaude.com.br/integracao/arquivo/","value":"77001","use":"usual"}],"status":"completed","subject":{"identifier":{"system":"https://www.acmesaude.com.br/integracao/paciente/","value":"507823709","use":"usual"},"type":"Patient"},"content":{"url":"https://arquivos.acmesaude.com.br/laudos/laudo-77001.pdf"}}'
};

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

**`Enviar por URL`**

```go Enviar por URL
package main

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

func main() {

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

	payload := strings.NewReader("{\n  \"resourceType\": \"Media\",\n  \"identifier\": [\n    {\n      \"system\": \"https://www.acmesaude.com.br/integracao/arquivo/\",\n      \"value\": \"77001\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"status\": \"completed\",\n  \"subject\": {\n    \"identifier\": {\n      \"system\": \"https://www.acmesaude.com.br/integracao/paciente/\",\n      \"value\": \"507823709\",\n      \"use\": \"usual\"\n    },\n    \"type\": \"Patient\"\n  },\n  \"content\": {\n    \"url\": \"https://arquivos.acmesaude.com.br/laudos/laudo-77001.pdf\"\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))

}
```

**`Enviar por URL`**

```ruby Enviar por URL
require 'uri'
require 'net/http'

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

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  \"resourceType\": \"Media\",\n  \"identifier\": [\n    {\n      \"system\": \"https://www.acmesaude.com.br/integracao/arquivo/\",\n      \"value\": \"77001\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"status\": \"completed\",\n  \"subject\": {\n    \"identifier\": {\n      \"system\": \"https://www.acmesaude.com.br/integracao/paciente/\",\n      \"value\": \"507823709\",\n      \"use\": \"usual\"\n    },\n    \"type\": \"Patient\"\n  },\n  \"content\": {\n    \"url\": \"https://arquivos.acmesaude.com.br/laudos/laudo-77001.pdf\"\n  }\n}"

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

**`Enviar por URL`**

```java Enviar por URL
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/Media")
  .header("x-api-key", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{\n  \"resourceType\": \"Media\",\n  \"identifier\": [\n    {\n      \"system\": \"https://www.acmesaude.com.br/integracao/arquivo/\",\n      \"value\": \"77001\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"status\": \"completed\",\n  \"subject\": {\n    \"identifier\": {\n      \"system\": \"https://www.acmesaude.com.br/integracao/paciente/\",\n      \"value\": \"507823709\",\n      \"use\": \"usual\"\n    },\n    \"type\": \"Patient\"\n  },\n  \"content\": {\n    \"url\": \"https://arquivos.acmesaude.com.br/laudos/laudo-77001.pdf\"\n  }\n}")
  .asString();
```

**`Enviar por URL`**

```php Enviar por URL
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://landing-zone-api.nilo.services/fhir/resources/Media', [
  'body' => '{
  "resourceType": "Media",
  "identifier": [
    {
      "system": "https://www.acmesaude.com.br/integracao/arquivo/",
      "value": "77001",
      "use": "usual"
    }
  ],
  "status": "completed",
  "subject": {
    "identifier": {
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709",
      "use": "usual"
    },
    "type": "Patient"
  },
  "content": {
    "url": "https://arquivos.acmesaude.com.br/laudos/laudo-77001.pdf"
  }
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'x-api-key' => '<apiKey>',
  ],
]);

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

**`Enviar por URL`**

```csharp Enviar por URL
using RestSharp;

var client = new RestClient("https://landing-zone-api.nilo.services/fhir/resources/Media");
var request = new RestRequest(Method.POST);
request.AddHeader("x-api-key", "<apiKey>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"resourceType\": \"Media\",\n  \"identifier\": [\n    {\n      \"system\": \"https://www.acmesaude.com.br/integracao/arquivo/\",\n      \"value\": \"77001\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"status\": \"completed\",\n  \"subject\": {\n    \"identifier\": {\n      \"system\": \"https://www.acmesaude.com.br/integracao/paciente/\",\n      \"value\": \"507823709\",\n      \"use\": \"usual\"\n    },\n    \"type\": \"Patient\"\n  },\n  \"content\": {\n    \"url\": \"https://arquivos.acmesaude.com.br/laudos/laudo-77001.pdf\"\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Enviar por URL`**

```swift Enviar por URL
import Foundation

let headers = [
  "x-api-key": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = [
  "resourceType": "Media",
  "identifier": [
    [
      "system": "https://www.acmesaude.com.br/integracao/arquivo/",
      "value": "77001",
      "use": "usual"
    ]
  ],
  "status": "completed",
  "subject": [
    "identifier": [
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709",
      "use": "usual"
    ],
    "type": "Patient"
  ],
  "content": ["url": "https://arquivos.acmesaude.com.br/laudos/laudo-77001.pdf"]
] as [String : Any]

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

let request = NSMutableURLRequest(url: NSURL(string: "https://landing-zone-api.nilo.services/fhir/resources/Media")! 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 é o recurso gravado, sem envelope:

### Response (200)

```json
{
  "resourceType": "Media",
  "identifier": [
    {
      "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--file-storage",
      "value": "918273",
      "use": "usual"
    },
    {
      "system": "https://www.acmesaude.com.br/integracao/arquivo/",
      "value": "77001",
      "use": "usual"
    }
  ],
  "status": "completed",
  "subject": {
    "identifier": {
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709",
      "use": "usual"
    },
    "reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4",
    "type": "Patient"
  },
  "content": {
    "url": "patients/44219/document/2026-08-20T14:31:02.884Z_Laudo_do_exame.pdf",
    "title": "Laudo_do_exame.pdf"
  },
  "id": "7b1d90c4-2f65-4a83-9c1e-1d84f0a53b27",
  "meta": {
    "lastUpdated": "2026-08-20T14:31:03.512000Z",
    "versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
  }
}
```

Guarde o `id`: é por ele que se faz a leitura direta. Ao lado do seu `identifier`, a resposta
traz o identificador Nilo do arquivo, no `system`
`…/NamingSystem/care-api--file-storage`.

> **Note**
>
> A resposta **não repete o que você enviou**: o `content` volta como a plataforma o registrou —
> o caminho de armazenamento em `url` e o nome do arquivo em `title` —, sem `data`,
> `contentType` nem `size`. É a visão da plataforma, e é o mesmo que uma leitura devolve.

### Por URL ou em base64

Há duas formas de mandar o conteúdo, e a escolha muda o nome do arquivo e as validações.

|                               | `content.url`                                                                           | `content.data`                                  |
| ----------------------------- | --------------------------------------------------------------------------------------- | ----------------------------------------------- |
| Como funciona                 | A plataforma **baixa** o arquivo do endereço informado                                  | O conteúdo vai em base64 na própria requisição  |
| Nome do arquivo               | Montado a partir do **nome do paciente** e da data — o `content.title` **é descartado** | Derivado do `content.title`                     |
| `content.contentType`         | Não é exigido nem conferido                                                             | **Obrigatório**, e só `application/pdf`         |
| O que decide o formato aceito | A **extensão no caminho da URL**, contra uma lista fechada                              | O `contentType` e os bytes do conteúdo          |
| Formatos aceitos              | PDF e também imagem, documento de texto, áudio e vídeo                                  | **Só PDF**                                      |
| Conferência do conteúdo       | Nenhuma além da extensão e do download                                                  | Base64 válido, PDF de verdade, tamanho e limite |

> **Warning**
>
> **`content.url` tem precedência.** Mandando os dois no mesmo payload, o `content.data` é
> **ignorado em silêncio** e o arquivo baixado da URL é o que fica. A chamada responde `200`.

> **Warning**
>
> **No envio por URL, o formato é decidido pela extensão no caminho da URL**, e não pelo
> `contentType`. A lista aceita é `.pdf`, `.jpg`, `.jpeg`, `.png`, `.gif`, `.doc`, `.docx`,
> `.xml`, `.txt`, `.mp3`, `.ogg`, `.oga`, `.wav` e `.mp4`.
>
> Duas consequências que pegam quem só espera PDF:
>
> * **URL sem extensão no caminho é recusada** — um endereço como
>   `https://arquivos.acmesaude.com.br/laudos/77001`, ou uma URL assinada cujo nome do objeto
>   não termina em `.pdf`, não passa. A recusa sai como `code: exception`, sem `expression`;
> * **por URL, dá para enviar coisa que não é PDF.** A restrição a `application/pdf` vale só
>   para o envio por `data`. Se a sua integração só deve mandar documentos, garanta isso do seu
>   lado — a API não vai barrar um `.jpg`.

> **Warning**
>
> O endereço tem de estar **acessível publicamente** no momento da chamada: é a plataforma que
> faz o download, e ela não recebe as suas credenciais. Uma URL assinada com prazo curto pode
> expirar antes. Certificado TLS inválido e resposta que não seja `2xx` também recusam a
> chamada, com `code: exception`.

### O nome do arquivo

As regras abaixo valem **só para o envio por `data`** — é o único caminho em que o
`content.title` sobrevive. No envio por URL o nome é montado pela plataforma como
*nome do paciente* + data, e o título que você mandou é descartado.

No envio por `data`, o título passa por uma normalização antes de virar nome de arquivo:

* acentos são transliterados (`ó` → `o`);
* tudo que não for letra, número, `.`, `_` ou `-` vira `_`;
* uma extensão `.pdf` já presente no título não é duplicada;
* o nome é cortado em 100 caracteres;
* `.`, `_` e `-` nas pontas são removidos.

| `content.title` enviado            | Nome do arquivo no Nilo Care |
| ---------------------------------- | ---------------------------- |
| `"Laudo do exame"`                 | `Laudo_do_exame.pdf`         |
| `"Relatório Médico.pdf"`           | `Relatorio_Medico.pdf`       |
| `"../../etc/Relatório Médico.pdf"` | `etc_Relatorio_Medico.pdf`   |
| ausente                            | `document.pdf`               |

### Request

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

**`Enviar o conteúdo em base64`**

```curl Enviar o conteúdo em base64
curl -X POST https://landing-zone-api.nilo.services/fhir/resources/Media \
     -H "x-api-key: <apiKey>" \
     -H "Content-Type: application/json" \
     -d '{
  "resourceType": "Media",
  "identifier": [
    {
      "system": "https://www.acmesaude.com.br/integracao/arquivo/",
      "value": "77002",
      "use": "usual"
    }
  ],
  "status": "completed",
  "subject": {
    "identifier": {
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709",
      "use": "usual"
    },
    "type": "Patient"
  },
  "content": {
    "title": "Laudo do exame",
    "contentType": "application/pdf",
    "data": "JVBERi0xLjQKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c+PgplbmRvYmoKdHJhaWxlcgo8PC9Sb290IDEgMCBSPj4KJSVFT0YK",
    "size": 72
  }
}'
```

**`Enviar o conteúdo em base64`**

```python Enviar o conteúdo em base64
import requests

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

payload = {
    "resourceType": "Media",
    "identifier": [
        {
            "system": "https://www.acmesaude.com.br/integracao/arquivo/",
            "value": "77002",
            "use": "usual"
        }
    ],
    "status": "completed",
    "subject": {
        "identifier": {
            "system": "https://www.acmesaude.com.br/integracao/paciente/",
            "value": "507823709",
            "use": "usual"
        },
        "type": "Patient"
    },
    "content": {
        "title": "Laudo do exame",
        "contentType": "application/pdf",
        "data": "JVBERi0xLjQKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c+PgplbmRvYmoKdHJhaWxlcgo8PC9Sb290IDEgMCBSPj4KJSVFT0YK",
        "size": 72
    }
}
headers = {
    "x-api-key": "<apiKey>",
    "Content-Type": "application/json"
}

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

print(response.json())
```

**`Enviar o conteúdo em base64`**

```javascript Enviar o conteúdo em base64
const url = 'https://landing-zone-api.nilo.services/fhir/resources/Media';
const options = {
  method: 'POST',
  headers: {'x-api-key': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"resourceType":"Media","identifier":[{"system":"https://www.acmesaude.com.br/integracao/arquivo/","value":"77002","use":"usual"}],"status":"completed","subject":{"identifier":{"system":"https://www.acmesaude.com.br/integracao/paciente/","value":"507823709","use":"usual"},"type":"Patient"},"content":{"title":"Laudo do exame","contentType":"application/pdf","data":"JVBERi0xLjQKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c+PgplbmRvYmoKdHJhaWxlcgo8PC9Sb290IDEgMCBSPj4KJSVFT0YK","size":72}}'
};

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

**`Enviar o conteúdo em base64`**

```go Enviar o conteúdo em base64
package main

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

func main() {

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

	payload := strings.NewReader("{\n  \"resourceType\": \"Media\",\n  \"identifier\": [\n    {\n      \"system\": \"https://www.acmesaude.com.br/integracao/arquivo/\",\n      \"value\": \"77002\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"status\": \"completed\",\n  \"subject\": {\n    \"identifier\": {\n      \"system\": \"https://www.acmesaude.com.br/integracao/paciente/\",\n      \"value\": \"507823709\",\n      \"use\": \"usual\"\n    },\n    \"type\": \"Patient\"\n  },\n  \"content\": {\n    \"title\": \"Laudo do exame\",\n    \"contentType\": \"application/pdf\",\n    \"data\": \"JVBERi0xLjQKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c+PgplbmRvYmoKdHJhaWxlcgo8PC9Sb290IDEgMCBSPj4KJSVFT0YK\",\n    \"size\": 72\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))

}
```

**`Enviar o conteúdo em base64`**

```ruby Enviar o conteúdo em base64
require 'uri'
require 'net/http'

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

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  \"resourceType\": \"Media\",\n  \"identifier\": [\n    {\n      \"system\": \"https://www.acmesaude.com.br/integracao/arquivo/\",\n      \"value\": \"77002\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"status\": \"completed\",\n  \"subject\": {\n    \"identifier\": {\n      \"system\": \"https://www.acmesaude.com.br/integracao/paciente/\",\n      \"value\": \"507823709\",\n      \"use\": \"usual\"\n    },\n    \"type\": \"Patient\"\n  },\n  \"content\": {\n    \"title\": \"Laudo do exame\",\n    \"contentType\": \"application/pdf\",\n    \"data\": \"JVBERi0xLjQKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c+PgplbmRvYmoKdHJhaWxlcgo8PC9Sb290IDEgMCBSPj4KJSVFT0YK\",\n    \"size\": 72\n  }\n}"

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

**`Enviar o conteúdo em base64`**

```java Enviar o conteúdo em base64
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/Media")
  .header("x-api-key", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{\n  \"resourceType\": \"Media\",\n  \"identifier\": [\n    {\n      \"system\": \"https://www.acmesaude.com.br/integracao/arquivo/\",\n      \"value\": \"77002\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"status\": \"completed\",\n  \"subject\": {\n    \"identifier\": {\n      \"system\": \"https://www.acmesaude.com.br/integracao/paciente/\",\n      \"value\": \"507823709\",\n      \"use\": \"usual\"\n    },\n    \"type\": \"Patient\"\n  },\n  \"content\": {\n    \"title\": \"Laudo do exame\",\n    \"contentType\": \"application/pdf\",\n    \"data\": \"JVBERi0xLjQKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c+PgplbmRvYmoKdHJhaWxlcgo8PC9Sb290IDEgMCBSPj4KJSVFT0YK\",\n    \"size\": 72\n  }\n}")
  .asString();
```

**`Enviar o conteúdo em base64`**

```php Enviar o conteúdo em base64
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://landing-zone-api.nilo.services/fhir/resources/Media', [
  'body' => '{
  "resourceType": "Media",
  "identifier": [
    {
      "system": "https://www.acmesaude.com.br/integracao/arquivo/",
      "value": "77002",
      "use": "usual"
    }
  ],
  "status": "completed",
  "subject": {
    "identifier": {
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709",
      "use": "usual"
    },
    "type": "Patient"
  },
  "content": {
    "title": "Laudo do exame",
    "contentType": "application/pdf",
    "data": "JVBERi0xLjQKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c+PgplbmRvYmoKdHJhaWxlcgo8PC9Sb290IDEgMCBSPj4KJSVFT0YK",
    "size": 72
  }
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'x-api-key' => '<apiKey>',
  ],
]);

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

**`Enviar o conteúdo em base64`**

```csharp Enviar o conteúdo em base64
using RestSharp;

var client = new RestClient("https://landing-zone-api.nilo.services/fhir/resources/Media");
var request = new RestRequest(Method.POST);
request.AddHeader("x-api-key", "<apiKey>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"resourceType\": \"Media\",\n  \"identifier\": [\n    {\n      \"system\": \"https://www.acmesaude.com.br/integracao/arquivo/\",\n      \"value\": \"77002\",\n      \"use\": \"usual\"\n    }\n  ],\n  \"status\": \"completed\",\n  \"subject\": {\n    \"identifier\": {\n      \"system\": \"https://www.acmesaude.com.br/integracao/paciente/\",\n      \"value\": \"507823709\",\n      \"use\": \"usual\"\n    },\n    \"type\": \"Patient\"\n  },\n  \"content\": {\n    \"title\": \"Laudo do exame\",\n    \"contentType\": \"application/pdf\",\n    \"data\": \"JVBERi0xLjQKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c+PgplbmRvYmoKdHJhaWxlcgo8PC9Sb290IDEgMCBSPj4KJSVFT0YK\",\n    \"size\": 72\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Enviar o conteúdo em base64`**

```swift Enviar o conteúdo em base64
import Foundation

let headers = [
  "x-api-key": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = [
  "resourceType": "Media",
  "identifier": [
    [
      "system": "https://www.acmesaude.com.br/integracao/arquivo/",
      "value": "77002",
      "use": "usual"
    ]
  ],
  "status": "completed",
  "subject": [
    "identifier": [
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709",
      "use": "usual"
    ],
    "type": "Patient"
  ],
  "content": [
    "title": "Laudo do exame",
    "contentType": "application/pdf",
    "data": "JVBERi0xLjQKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c+PgplbmRvYmoKdHJhaWxlcgo8PC9Sb290IDEgMCBSPj4KJSVFT0YK",
    "size": 72
  ]
] as [String : Any]

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

let request = NSMutableURLRequest(url: NSURL(string: "https://landing-zone-api.nilo.services/fhir/resources/Media")! 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 que é conferido no envio por `data`

Nesta ordem, e todas as recusas são `400`:

1. **O `identifier` é casado antes de tudo.** Chave já usada é recusada aqui, sem que o
   paciente ou o conteúdo cheguem a ser olhados. Antes disso, o recurso ainda passa pela
   validação de forma do FHIR, que recusa com `code: structure`.
2. **O paciente é resolvido em seguida.** Arquivo de paciente que não existe não é decodificado
   nem sobe — não há resíduo de uma chamada recusada.
3. `content.contentType` presente e igual a `application/pdf`.
4. `content.data` é base64 válido. Espaços e quebras de linha **são tolerados**: um base64
   quebrado em 76 colunas funciona.
5. O conteúdo decodificado não é vazio.
6. O conteúdo decodificado não passa de **10485760 bytes (10 MiB)**.
7. `content.size`, se você mandou, bate exatamente com o tamanho decodificado.
8. O conteúdo **é** um PDF: os primeiros bytes precisam ser `%PDF-`. Um arquivo de outro tipo
   com `contentType: application/pdf` é recusado aqui.

> **Note**
>
> O limite de 10 MiB vale para o conteúdo **depois** de decodificado, não para o tamanho do
> corpo da requisição — em base64 o payload é cerca de um terço maior. A mensagem do erro
> `too-long` sempre informa o limite exato em bytes do seu ambiente.

### O paciente

O paciente vem em `subject.identifier`, e é **só** por aí:

```json
"subject": {
  "identifier": {
    "system": "https://www.acmesaude.com.br/integracao/paciente/",
    "value": "507823709"
  },
  "type": "Patient"
}
```

> **Warning**
>
> **`subject.reference` sozinho não resolve o paciente**, mesmo apontando para um `Patient` que
> existe. Sem `subject.identifier` a chamada é recusada, e o erro sai como `code: exception`,
> sem `expression` — veja [Erros](#erros). Mande sempre o identificador.

O identificador pode ser o do seu sistema ou o identificador Nilo do paciente; nos dois casos
ele tem de resolver para um paciente do seu ambiente. Não resolvendo, a recusa é
`Patient does not exist`.

## Buscar

### Request

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

**`Busca com resultados`**

```curl Busca com resultados
curl -G https://landing-zone-api.nilo.services/fhir/resources/Media \
     -H "x-api-key: <apiKey>" \
     -d _count=50 \
     -d _lastUpdated=eq2013-01-14 \
     --data-urlencode identifier=https://www.acmesaude.com.br/integracao/arquivo/|77001 \
     --data-urlencode patient=Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4 \
     --data-urlencode patient:identifier=https://www.acmesaude.com.br/integracao/paciente/|507823709 \
     -d status=completed \
     --data-urlencode subject=Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4 \
     --data-urlencode subject:identifier=https://www.acmesaude.com.br/integracao/paciente/|507823709
```

**`Busca com resultados`**

```python Busca com resultados
import requests

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

querystring = {"_count":"50","_lastUpdated":"[\"eq2013-01-14\"]","identifier":"https://www.acmesaude.com.br/integracao/arquivo/|77001","patient":"Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4","patient:identifier":"https://www.acmesaude.com.br/integracao/paciente/|507823709","status":"completed","subject":"Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4","subject:identifier":"https://www.acmesaude.com.br/integracao/paciente/|507823709"}

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/Media?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Farquivo%2F%7C77001&patient=Patient%2Fba200cfa-dae0-46cf-81a0-008e3f7414b4&patient%3Aidentifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709&status=completed&subject=Patient%2Fba200cfa-dae0-46cf-81a0-008e3f7414b4&subject%3Aidentifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709';
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/Media?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Farquivo%2F%7C77001&patient=Patient%2Fba200cfa-dae0-46cf-81a0-008e3f7414b4&patient%3Aidentifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709&status=completed&subject=Patient%2Fba200cfa-dae0-46cf-81a0-008e3f7414b4&subject%3Aidentifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709"

	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/Media?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Farquivo%2F%7C77001&patient=Patient%2Fba200cfa-dae0-46cf-81a0-008e3f7414b4&patient%3Aidentifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709&status=completed&subject=Patient%2Fba200cfa-dae0-46cf-81a0-008e3f7414b4&subject%3Aidentifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709")

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/Media?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Farquivo%2F%7C77001&patient=Patient%2Fba200cfa-dae0-46cf-81a0-008e3f7414b4&patient%3Aidentifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709&status=completed&subject=Patient%2Fba200cfa-dae0-46cf-81a0-008e3f7414b4&subject%3Aidentifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709")
  .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/Media?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Farquivo%2F%7C77001&patient=Patient%2Fba200cfa-dae0-46cf-81a0-008e3f7414b4&patient%3Aidentifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709&status=completed&subject=Patient%2Fba200cfa-dae0-46cf-81a0-008e3f7414b4&subject%3Aidentifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709', [
  '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/Media?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Farquivo%2F%7C77001&patient=Patient%2Fba200cfa-dae0-46cf-81a0-008e3f7414b4&patient%3Aidentifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709&status=completed&subject=Patient%2Fba200cfa-dae0-46cf-81a0-008e3f7414b4&subject%3Aidentifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709");
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/Media?_count=50&_lastUpdated=%5B%22eq2013-01-14%22%5D&identifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Farquivo%2F%7C77001&patient=Patient%2Fba200cfa-dae0-46cf-81a0-008e3f7414b4&patient%3Aidentifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709&status=completed&subject=Patient%2Fba200cfa-dae0-46cf-81a0-008e3f7414b4&subject%3Aidentifier=https%3A%2F%2Fwww.acmesaude.com.br%2Fintegracao%2Fpaciente%2F%7C507823709")! 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`:

### Response (200)

```json
{
  "resourceType": "Bundle",
  "type": "searchset",
  "entry": [
    {
      "fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/Media/7b1d90c4-2f65-4a83-9c1e-1d84f0a53b27",
      "resource": {
        "resourceType": "Media",
        "identifier": [
          {
            "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--file-storage",
            "value": "918273",
            "use": "usual"
          },
          {
            "system": "https://www.acmesaude.com.br/integracao/arquivo/",
            "value": "77001",
            "use": "usual"
          }
        ],
        "status": "completed",
        "subject": {
          "identifier": {
            "system": "https://www.acmesaude.com.br/integracao/paciente/",
            "value": "507823709",
            "use": "usual"
          },
          "reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4",
          "type": "Patient"
        },
        "content": {
          "url": "patients/44219/document/2026-08-20T14:31:02.884Z_Laudo_do_exame.pdf",
          "title": "Laudo_do_exame.pdf"
        },
        "id": "7b1d90c4-2f65-4a83-9c1e-1d84f0a53b27"
      },
      "search": {
        "mode": "match"
      }
    },
    {
      "fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/Media/c58f2a19-70d4-4be6-9a02-3ef17c8b4d51",
      "resource": {
        "resourceType": "Media",
        "identifier": [
          {
            "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--file-storage",
            "value": "918274",
            "use": "usual"
          }
        ],
        "status": "completed",
        "subject": {
          "identifier": {
            "system": "https://www.acmesaude.com.br/integracao/paciente/",
            "value": "507823709",
            "use": "usual"
          },
          "reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4",
          "type": "Patient"
        },
        "content": {
          "url": "patients/44219/image/2026-08-21T09:12:44.117Z_foto-receita.jpg",
          "title": "foto-receita.jpg"
        },
        "id": "c58f2a19-70d4-4be6-9a02-3ef17c8b4d51"
      },
      "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 arquivo, em `system\|value`. Aceita a sua chave ou o identificador Nilo do arquivo | `Media.identifier`         |
| `subject:identifier`             | [token](https://hl7.org/fhir/R4/search.html#token)         | Arquivos de um paciente, pelo identificador dele                                                    | `Media.subject.identifier` |
| `subject`                        | [reference](https://hl7.org/fhir/R4/search.html#reference) | Arquivos de um paciente, pelo `id` Nilo FHIR dele                                                   | `Media.subject`            |
| `patient:identifier` · `patient` | idem                                                       | Sinônimos dos dois acima: aqui o `subject` é sempre um paciente                                     | `Media.subject`            |
| `status`                         | [token](https://hl7.org/fhir/R4/search.html#token)         | Aceito, e inútil: todo arquivo é `completed`                                                        | `Media.status`             |
| `_lastUpdated`                   | [date](https://hl7.org/fhir/R4/search.html#date)           | Data da última gravação no store, com os prefixos `eq`, `ge`, `le`                                  | —                          |

A busca útil é a dos arquivos de um paciente — **um `GET` sem nenhum filtro devolve os
arquivos de todos os pacientes do seu ambiente**, página por página, o que raramente é o que
se quer:

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

> **Note**
>
> Os demais parâmetros canônicos do `Media` existem e **não encontram nada** aqui, porque a
> Nilo não preenche o campo correspondente: `type`, `modality`, `view`, `created`, `encounter`,
> `operator`, `device`, `site` e `based-on`. A exceção é o campo que **você mesmo** tenha
> enviado: ele fica no recurso e passa a ser encontrável — mais um motivo para omitir o que a
> plataforma não usa.

> **Warning**
>
> Qual identificador a referência do paciente carrega **depende da sua implantação**. Na
> configuração que usa identificadores externos nas referências, `subject` traz o identificador
> do seu sistema e o filtro acima funciona como está. Sem ela, vem o identificador Nilo do
> paciente, e é esse `system` que você tem de usar no filtro. Confira numa resposta de leitura
> qual dos dois está lá antes de montar a busca em volume.

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

### A busca não devolve só o que você enviou

> **Warning**
>
> **A consulta expõe todos os arquivos do paciente, e não só PDF.** Anexos que chegaram por
> outros canais — foto, áudio e vídeo trocados na conversa com o paciente, por exemplo — também
> saem como `Media` quando estão associados ao paciente. E como o `content.contentType` **não** é preenchido na leitura, não há
> campo que diga o tipo: se a sua integração só trata documentos, olhe a extensão no
> `content.title`.

> **Note**
>
> Arquivos criados dentro do Nilo Care aparecem na consulta com **apenas** o identificador Nilo,
> no `system` `…/NamingSystem/care-api--file-storage`. Só os que vieram por integração trazem
> também a sua chave. É por essa diferença que você separa uns dos outros.
>
> Arquivo que não esteja associado a um paciente não é exposto por esta API.

> **Warning**
>
> **`content.url` na leitura não é um link de download.** Para os arquivos enviados por
> integração é o caminho de armazenamento — algo como
> `patients/{id}/document/{timestamp}_arquivo.pdf` —, e um `GET` nesse valor não baixa nada. O
> formato varia conforme a origem do arquivo, e em alguns casos é um endereço completo; não
> construa a sua integração em cima dessa diferença.
>
> Esta API **não** entrega o conteúdo dos arquivos: ela expõe o registro deles. Para obter o
> arquivo em si, use a fonte que você já tem — no envio por URL, o seu próprio endereço de
> origem.

## Ler por ID

### Request

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

**`Arquivo encontrado`**

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

**`Arquivo encontrado`**

```python Arquivo encontrado
import requests

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

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

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

print(response.json())
```

**`Arquivo encontrado`**

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

**`Arquivo encontrado`**

```go Arquivo encontrado
package main

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

func main() {

	url := "https://landing-zone-api.nilo.services/fhir/resources/Media/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))

}
```

**`Arquivo encontrado`**

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

url = URI("https://landing-zone-api.nilo.services/fhir/resources/Media/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
```

**`Arquivo encontrado`**

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

**`Arquivo encontrado`**

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

$client = new \GuzzleHttp\Client();

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

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

**`Arquivo encontrado`**

```csharp Arquivo encontrado
using RestSharp;

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

**`Arquivo encontrado`**

```swift Arquivo encontrado
import Foundation

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

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

> **Warning**
>
> Diferente da busca, esta leitura não devolve um `Bundle` — mas também **não devolve o recurso
> nu**. A resposta é um envelope com `fullUrl`, `search` e `resource`, e o arquivo está em
> `resource`. Ler `content` ou `subject` na raiz da resposta não encontra nada.

### Response (200)

```json
{
  "fullUrl": "https://landing-zone-api.nilo.services/fhir/resources/Media/7b1d90c4-2f65-4a83-9c1e-1d84f0a53b27",
  "resource": {
    "resourceType": "Media",
    "identifier": [
      {
        "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--file-storage",
        "value": "918273",
        "use": "usual"
      },
      {
        "system": "https://www.acmesaude.com.br/integracao/arquivo/",
        "value": "77001",
        "use": "usual"
      }
    ],
    "status": "completed",
    "subject": {
      "identifier": {
        "system": "https://www.acmesaude.com.br/integracao/paciente/",
        "value": "507823709",
        "use": "usual"
      },
      "reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4",
      "type": "Patient"
    },
    "content": {
      "url": "patients/44219/document/2026-08-20T14:31:02.884Z_Laudo_do_exame.pdf",
      "title": "Laudo_do_exame.pdf"
    },
    "id": "7b1d90c4-2f65-4a83-9c1e-1d84f0a53b27",
    "meta": {
      "lastUpdated": "2026-08-20T14:31:03.512000Z",
      "versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
    }
  },
  "search": {
    "mode": "match"
  }
}
```

A leitura por ID responde `404` quando o `id` não existe — inclusive quando o arquivo existia
e foi excluído no Nilo Care.

## Valores aceitos

### `content.contentType`

Um só: `application/pdf`. Qualquer outro valor é recusado com `not-supported`, e o conteúdo
ainda é conferido byte a byte contra o formato — declarar PDF não basta, tem de ser PDF.

A restrição vale para o **envio por `data`**. No envio por URL quem decide é a extensão da
URL, e ela aceita mais formatos — veja [Por URL ou em base64](#por-url-ou-em-base64). E a
leitura devolve arquivos de qualquer formato, porque devolve tudo que o paciente tem.

### `status`

Um só: `completed`. É o que a leitura sempre devolve, é o único que a referência declara e é
o que você deve enviar. Os outros valores do FHIR R4 não são usados: a plataforma não guarda
situação de arquivo, e o valor devolvido é sempre `completed`.

## Efeitos colaterais

> **Warning**
>
> **Reenviar um `identifier` já usado não atualiza — recusa.** Não há como trocar o paciente nem
> o conteúdo de um arquivo já enviado: para isso, mande um arquivo novo com chave nova e peça à
> equipe que exclua o anterior no Nilo Care.

> **Note**
>
> O **nome**, esse sim, muda depois: a equipe pode renomear o arquivo no Nilo Care, e o nome novo
> passa a ser o que a leitura devolve em `content.title`. Não trate o `title` como o valor que
> você enviou.

> **Note**
>
> Se o arquivo foi **excluído no Nilo Care**, o registro deixa de existir para esta API — a
> consulta não o devolve mais, e a chave que ele usava volta a estar livre. Reenviar aquele
> mesmo `identifier` depois disso cria um arquivo novo, em vez de ser recusado.

> **Note**
>
> Falhando **o registro do arquivo**, o conteúdo que já subiu é apagado — nesse caso a chamada
> recusada não deixa arquivo órfão.

> **Warning**
>
> **Um erro depois do registro não desfaz o arquivo.** O apagamento acima cobre a falha do
> registro em si; se a chamada falhar num passo posterior, você recebe `400` mas o arquivo
> **já está na ficha do paciente**. E como nada foi gravado do lado FHIR, repetir a chamada com
> a **mesma** chave não é reconhecido como reenvio: cria um segundo arquivo. Depois de um erro,
> confira a ficha antes de repetir.

> **Note**
>
> Este endpoint nunca responde `204`: não há remoção de arquivo por integração.

## Erros

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

| `code`          | `expression`                | Mensagem                                                                                                     | Quando                                                                   |
| --------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------ |
| `required`      | `Media.identifier`          | `Field is required`                                                                                          | O payload não tem `identifier`                                           |
| `business-rule` | `Media.identifier`          | `Unable to use any of the provided identifiers to match an existing resource, which can lead to duplicates.` | Há `identifier`, mas nenhum utilizável — falta `system` ou falta `value` |
| `required`      | `Media.subject`             | `Field is required`                                                                                          | O payload não tem `subject`                                              |
| `not-found`     | `Media.subject`             | `Patient does not exist`                                                                                     | O `subject.identifier` não resolve para um paciente do seu ambiente      |
| `required`      | `Media.content`             | `Either content.url or content.data is required`                                                             | Nem `url` nem `data` no `content`                                        |
| `required`      | `Media.content.contentType` | `Field is required`                                                                                          | Envio por `data` sem `contentType`                                       |
| `not-supported` | `Media.content.contentType` | `The contentType '…' is not supported. Only 'application/pdf' is supported.`                                 | `contentType` diferente de `application/pdf`                             |
| `invalid`       | `Media.content.data`        | `Field is not a valid base64-encoded content`                                                                | O `data` não é base64 válido                                             |
| `required`      | `Media.content.data`        | `Field is required`                                                                                          | O `data` é base64 válido, mas decodifica para nada                       |
| `too-long`      | `Media.content.data`        | `Field exceeds the maximum allowed size of 10485760 bytes`                                                   | Conteúdo acima do limite do ambiente                                     |
| `invalid`       | `Media.content.size`        | `Field does not match the content size of … bytes`                                                           | O `size` enviado não bate com o conteúdo                                 |
| `invalid`       | `Media.content.data`        | `Field content is not a valid PDF file`                                                                      | O conteúdo não começa com `%PDF-`                                        |
| `exception`     | —                           | `PermissionDenied: Update Media is not allowed.`                                                             | O `identifier` enviado já corresponde a um arquivo                       |
| `exception`     | —                           | `FieldRequiredError: ['Field reference.identifier is required']`                                             | `subject` sem `identifier`                                               |
| `exception`     | —                           | `Unsupported file type: …`                                                                                   | Envio por URL cujo caminho não termina em uma extensão reconhecida       |
| `exception`     | —                           | mensagem do erro HTTP, ou `The SSL certificate for the URL is not valid.`                                    | Envio por URL que não pôde ser baixada                                   |

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

### Response (200)

```json
{
  "resourceType": "Media",
  "identifier": [
    {
      "system": "https://landing-zone-api.nilo.services/fhir/resources/NamingSystem/care-api--file-storage",
      "value": "918273",
      "use": "usual"
    },
    {
      "system": "https://www.acmesaude.com.br/integracao/arquivo/",
      "value": "77001",
      "use": "usual"
    }
  ],
  "status": "completed",
  "subject": {
    "identifier": {
      "system": "https://www.acmesaude.com.br/integracao/paciente/",
      "value": "507823709",
      "use": "usual"
    },
    "reference": "Patient/ba200cfa-dae0-46cf-81a0-008e3f7414b4",
    "type": "Patient"
  },
  "content": {
    "url": "patients/44219/document/2026-08-20T14:31:02.884Z_Laudo_do_exame.pdf",
    "title": "Laudo_do_exame.pdf"
  },
  "id": "7b1d90c4-2f65-4a83-9c1e-1d84f0a53b27",
  "meta": {
    "lastUpdated": "2026-08-20T14:31:03.512000Z",
    "versionId": "MTc4NjAyMTQ1MjkwNTAwMDM2Nw"
  }
}
```

> **Warning**
>
> **As quatro últimas linhas da tabela não são validações — são falhas não tratadas**, e a
> primeira delas é o caso mais comum deste recurso: o reenvio de uma chave. O `400` sai com
> `code: exception`, sem `expression`, e com uma mensagem de erro de linguagem em vez de uma
> explicação do campo.
>
> Nenhuma delas é contrato: não tente interpretar o texto. Trate `code: exception` como
> "payload recusado, motivo não classificado" e confira a chave, o `subject` e a URL enviados.