Pular para o conteúdo principal

Cadastrar

EndpointPOST /fhir/resources/Media
Autenticação🔓 Chave de API
StatusImplementado
Comportamento
  • O campo identifier é obrigatório e deve ser novo e único a cada arquivo: não existe atualização de Media.
  • O campo subject é obrigatório, e o subject.identifier também: é por ele que o paciente é resolvido. Enviar apenas o subject.reference resulta em erro.
  • Envie o arquivo por content.url ou por content.data (base64). O content.url tem precedência quando os dois são enviados.
  • O content.title só é preservado como nome do arquivo no envio em base64. No envio por URL o nome é definido pelo NiloCare.
  • Somente application/pdf, com limite de 10 MiB (10485760 bytes).
  • Não há PUT nem DELETE para este recurso.

Modelagem da API - Request


OpçãoTipoRequeridoDescriçãoExemplo
x-api-keystringSimChave de autenticação do cliente, fornecida durante a configuração do ambiente.
Content-TypestringSimapplication/json


Envio por URL

O NiloCare baixa o arquivo a partir da URL informada em content.url. Use esse fluxo para arquivos grandes ou que já estejam publicados em um endereço acessível.

Nome do arquivo

Nesse fluxo o nome do arquivo é definido pelo NiloCare a partir do paciente — o content.title não é preservado como nome do arquivo. Para controlar o nome, use o envio em base64.

Enviar arquivo por URL

curl --request POST \
--url https://landing-zone-api.nilo.services/fhir/resources/Media \
--header 'Content-Type: application/json' \
--header 'x-api-key: <inserir API Key aqui>' \
--data '{
"resourceType": "Media",
"identifier": [
{
"system": "https://www.acmesaude.com.br/integracao/arquivo",
"use": "usual",
"value": "77001"
}
],
"status": "completed",
"subject": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente",
"value": "456"
},
"type": "Patient"
},
"content": {
"contentType": "application/pdf",
"url": "https://arquivos.acmesaude.com.br/laudos/laudo-77001.pdf",
"title": "Laudo do exame"
}
}'


Envio do conteúdo em base64

O conteúdo enviado em content.data é decodificado, validado e armazenado pelo NiloCare, preservando o nome derivado de content.title. Nesse fluxo o content.contentType é obrigatório.

Enviar arquivo em base64

curl --request POST \
--url https://landing-zone-api.nilo.services/fhir/resources/Media \
--header 'Content-Type: application/json' \
--header 'x-api-key: <inserir API Key aqui>' \
--data '{
"resourceType": "Media",
"identifier": [
{
"system": "https://www.acmesaude.com.br/integracao/arquivo",
"use": "usual",
"value": "77002"
}
],
"status": "completed",
"subject": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente",
"value": "456"
},
"type": "Patient"
},
"content": {
"contentType": "application/pdf",
"title": "Laudo do exame",
"data": "JVBERi0xLjQKMSAwIG9iajw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAyIDAgUj4+ZW5kb2JqCjIgMCBvYmo8PC9UeXBlL1BhZ2VzL0tpZHNbMyAwIFJdL0NvdW50IDE+PmVuZG9iagozIDAgb2JqPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9NZWRpYUJveFswIDAgNTk1IDg0Ml0+PmVuZG9iagp4cmVmCjAgNAowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1MiAwMDAwMCBuIAowMDAwMDAwMTAxIDAwMDAwIG4gCnRyYWlsZXI8PC9TaXplIDQvUm9vdCAxIDAgUj4+CnN0YXJ0eHJlZgoxNjQKJSVFT0YK"
}
}'

nota

O content.data do exemplo acima é um PDF mínimo válido — uma única página em branco — para manter a requisição legível.

Nome do arquivo (content.title)

As regras abaixo valem apenas para o envio em base64 — é o único fluxo em que o content.title é preservado. Nele, o nome do arquivo é derivado do content.title da seguinte forma:

  • acentos são transliterados (óo);
  • caracteres que não sejam letras, números, ., _ ou - são substituídos por _;
  • uma extensão .pdf já presente no título não é duplicada;
  • o nome é truncado em 100 caracteres;
  • ., _ e - nas extremidades são removidos;
  • sem content.title, o arquivo é nomeado document.pdf.
content.title enviadoNome do arquivo no NiloCare
"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
ausentedocument.pdf
Tamanho do payload

O arquivo é limitado a 10 MiB (10485760 bytes).

Modelagem da API - Response


Operação bem sucedida.
resourceType
required
any
Value: "Media"
id
string (id) ^[A-Za-z0-9\-\.]{{1,64}}$

Qualquer combinação de letras, números, "-" e ".", com um limite de 64 caracteres. (Pode ser um número inteiro, um OID não prefixado, UUID ou qualquer outro padrão de identificador que atenda a essas restrições.) Os IDs não diferenciam maiúsculas de minúsculas.

object (Meta)

Os metadados sobre um recurso. Este conteúdo do recurso é normalmente mantido pelo sistema gestor do registro.

required
Array of objects (Identifier) non-empty

Identificador do arquivo no sistema de origem. Obrigatório e deve ser novo e único a cada arquivo: não há atualização de Media.

status
required
any

Obrigatório pela especificação FHIR, porém ignorado na escrita: o NiloCare não armazena o status do arquivo. A consulta sempre retorna completed.

Value: "completed"
required
object

Paciente ao qual o arquivo será associado. A resolução usa exclusivamente o subject.identifier, que é obrigatório — o reference literal é ignorado. Informe subject.type como Patient; quando ausente, a API assume esse valor.

required
Envio por URL (object) or Envio em base64 (object)

Conteúdo do arquivo. Informe content.url ou content.data.

{
  • "resourceType": "Media",
  • "id": "903dAAe9-c57f-4eb3-bd1c-65XXd41exx81",
  • "meta": {
    },
  • "identifier": [
    ],
  • "status": "completed",
  • "subject": {},
  • "content": {}
}

Possíveis Erros


identifier não informado

O identifier é obrigatório e é usado para verificar se o arquivo já existe.

Erro retornado

{
"issue": [
{
"code": "required",
"details": {
"text": "Field is required"
},
"expression": [
"Media.identifier"
],
"severity": "error"
}
],
"resourceType": "OperationOutcome"
}

Exemplo de payload que gera o erro

{
"resourceType": "Media",
"status": "completed",
"subject": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente",
"value": "456"
},
"type": "Patient"
},
"content": {
"contentType": "application/pdf",
"url": "https://arquivos.acmesaude.com.br/laudos/laudo-77001.pdf",
"title": "Laudo do exame"
}
}

identifier já utilizado (atualização não permitida)

Se qualquer um dos identifier enviados corresponder a um arquivo já existente, a requisição é rejeitada — Media não pode ser atualizado. Envie sempre um identifier novo a cada arquivo.

Pré-condição do exemplo abaixo: já existe um Media com o identifier informado.

Erro retornado

{
"issue": [
{
"code": "exception",
"details": {
"text": "PermissionDenied: Update Media is not allowed."
},
"severity": "error"
}
],
"resourceType": "OperationOutcome"
}

Exemplo de payload que gera o erro

{
"resourceType": "Media",
"identifier": [
{
"system": "https://www.acmesaude.com.br/integracao/arquivo",
"use": "usual",
"value": "77001"
}
],
"status": "completed",
"subject": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente",
"value": "456"
},
"type": "Patient"
},
"content": {
"contentType": "application/pdf",
"url": "https://arquivos.acmesaude.com.br/laudos/laudo-77002.pdf",
"title": "Outro laudo"
}
}

subject não informado

O paciente é obrigatório e é resolvido antes de qualquer processamento do arquivo.

Erro retornado

{
"issue": [
{
"code": "required",
"details": {
"text": "Field is required"
},
"expression": [
"Media.subject"
],
"severity": "error"
}
],
"resourceType": "OperationOutcome"
}

Exemplo de payload que gera o erro

{
"resourceType": "Media",
"identifier": [
{
"system": "https://www.acmesaude.com.br/integracao/arquivo",
"use": "usual",
"value": "77003"
}
],
"status": "completed",
"content": {
"contentType": "application/pdf",
"url": "https://arquivos.acmesaude.com.br/laudos/laudo-77003.pdf",
"title": "Laudo do exame"
}
}

subject sem identifier

O paciente é resolvido exclusivamente pelo subject.identifier. Enviar apenas o subject.reference — ainda que ele aponte para um Patient existente no store — não é suficiente, e o erro retornado é genérico (sem expression).

Erro retornado

{
"issue": [
{
"code": "exception",
"details": {
"text": "FieldRequiredError: ['Field reference.identifier is required']"
},
"severity": "error"
}
],
"resourceType": "OperationOutcome"
}

Exemplo de payload que gera o erro

{
"resourceType": "Media",
"identifier": [
{
"system": "https://www.acmesaude.com.br/integracao/arquivo",
"use": "usual",
"value": "77010"
}
],
"status": "completed",
"subject": {
"reference": "Patient/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"type": "Patient"
},
"content": {
"contentType": "application/pdf",
"url": "https://arquivos.acmesaude.com.br/laudos/laudo-77003.pdf",
"title": "Laudo do exame"
}
}

Paciente do subject não existe

O paciente informado no subject.identifier não foi encontrado no NiloCare. Cadastre o paciente antes de enviar o arquivo.

Erro retornado

{
"issue": [
{
"code": "not-found",
"details": {
"text": "Patient does not exist"
},
"expression": [
"Media.subject"
],
"severity": "error"
}
],
"resourceType": "OperationOutcome"
}

Exemplo de payload que gera o erro

{
"resourceType": "Media",
"identifier": [
{
"system": "https://www.acmesaude.com.br/integracao/arquivo",
"use": "usual",
"value": "77004"
}
],
"status": "completed",
"subject": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente",
"value": "999999999"
},
"type": "Patient"
},
"content": {
"contentType": "application/pdf",
"url": "https://arquivos.acmesaude.com.br/laudos/laudo-77004.pdf",
"title": "Laudo do exame"
}
}

Nem content.url nem content.data informados

É preciso informar uma das duas formas de envio do arquivo.

Erro retornado

{
"issue": [
{
"code": "required",
"details": {
"text": "Either content.url or content.data is required"
},
"expression": [
"Media.content"
],
"severity": "error"
}
],
"resourceType": "OperationOutcome"
}

Exemplo de payload que gera o erro

{
"resourceType": "Media",
"identifier": [
{
"system": "https://www.acmesaude.com.br/integracao/arquivo",
"use": "usual",
"value": "77005"
}
],
"status": "completed",
"subject": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente",
"value": "456"
},
"type": "Patient"
},
"content": {
"contentType": "application/pdf",
"title": "Laudo do exame"
}
}

contentType não suportado

No envio em base64, somente application/pdf é aceito.

Erro retornado

{
"issue": [
{
"code": "not-supported",
"details": {
"text": "The contentType 'image/png' is not supported. Only 'application/pdf' is supported."
},
"expression": [
"Media.content.contentType"
],
"severity": "error"
}
],
"resourceType": "OperationOutcome"
}

Exemplo de payload que gera o erro

{
"resourceType": "Media",
"identifier": [
{
"system": "https://www.acmesaude.com.br/integracao/arquivo",
"use": "usual",
"value": "77006"
}
],
"status": "completed",
"subject": {
"identifier": {
"system": "https://www.acmesaude.com.br/integracao/paciente",
"value": "456"
},
"type": "Patient"
},
"content": {
"contentType": "image/png",
"title": "Exame de imagem",
"data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVR4nGP6DwABAgEAX9TQMQAAAABJRU5ErkJggg=="
}
}

Demais validações do conteúdo em base64

As validações abaixo são aplicadas nesta ordem, todas com severity: "error" e no formato OperationOutcome. Como os payloads diferem apenas no valor de content.data / content.size, os cenários estão resumidos na tabela:

Cenáriocodedetails.textexpression
content.contentType não informadorequiredField is requiredMedia.content.contentType
content.data não é base64 válidoinvalidField is not a valid base64-encoded contentMedia.content.data
content.data decodifica para conteúdo vaziorequiredField is requiredMedia.content.data
Conteúdo acima do limitetoo-longField exceeds the maximum allowed size of 10485760 bytesMedia.content.data
content.size divergenteinvalidField does not match the content size of 20481 bytesMedia.content.size
Conteúdo não é um PDFinvalidField content is not a valid PDF fileMedia.content.data
nota
  • Espaços e quebras de linha no content.data são tolerados — payloads base64 quebrados em 76 colunas funcionam normalmente.
  • O content.hash é aceito, mas não é validado.
  • Na mensagem do erro de content.size, o valor 20481 é substituído pelo tamanho real do conteúdo decodificado.