Estudos

Endpoints para consultar estudos DICOM ingeridos pelo sistema. Todos são read-only via API — a criação acontece automaticamente via webhook do Orthanc quando um estudo é estabilizado. Isolamento multi-tenant: aplicado via scopes Eloquent (BelongsToTenantAndUnit). Usuários regulares enxergam só estudos da sua unidade; tenant admins enxergam todas as unidades do tenant; super admins enxergam tudo. Endpoints de report aninhados em /studies/{id}/reports/* estão documentados em Laudos.

GET /api/studies

Lista paginada de estudos acessíveis ao usuário. Auth: auth:api

Query params

Busca case-insensitive em patient_name, patient_id e accession_number. Máximo 255 caracteres.
patient_uuid
uuid
Filtro exato pela FK patient_uuid.
exclude_id
uuid
Exclui o estudo com esse id da listagem (útil para “estudos relacionados”).
page
integer
default:"1"
Página da paginação.

Response 200

Paginação Laravel padrão (15 itens por página, não customizável).
{
  "data": [
    {
      "id": "uuid",
      "tenant_id": "uuid",
      "unit_id": "uuid",
      "patient_uuid": "uuid",
      "orthanc_study_id": "string",
      "study_instance_uid": "string",
      "patient_id": "string",
      "patient_name": "string",
      "patient_birth_date": "YYYY-MM-DD | null",
      "patient_sex": "M | F | null",
      "accession_number": "string | null",
      "study_date": "YYYY-MM-DD",
      "study_description": "string | null",
      "modalities": ["CT", "CR", ...] ,
      "report_status": "pending | draft | final | null",
      "reported_at": "iso8601 | null",
      "reported_by_user_id": "uuid | null",
      "created_at": "iso8601",
      "updated_at": "iso8601"
    }
  ],
  "current_page": 1,
  "per_page": 15,
  "total": 123,
  "last_page": 9
}

Notas

  • Ordenação: study_date DESC, created_at DESC
  • O campo modalities pode vir null no índex se o worker ainda não indexou as séries — nesse caso, use GET /api/studies/{id} que aplica fallback

GET /api/studies/

Retorna o detalhe de um estudo com relacionamentos patient, unit, tenant. Auth: auth:api

Path params

ParamTipoDescrição
iduuidID do estudo

Response 200

Mesmo shape do index, mais:
{
  "...": "campos do estudo",
  "patient": {
    "id": "uuid",
    "tenant_id": "uuid",
    "patient_id": "string",
    "patient_name": "string",
    "patient_birth_date": "YYYY-MM-DD | null",
    "patient_sex": "M | F | null",
    "created_at": "iso8601",
    "updated_at": "iso8601"
  },
  "unit": {
    "id": "uuid",
    "tenant_id": "uuid",
    "name": "string"
  },
  "tenant": {
    "id": "uuid",
    "name": "string"
  }
}

Fallback de modalities

Se o campo modalities do model estiver null (worker ainda não atualizou), o controller calcula dinamicamente agrupando series.modality únicos. Garante que o campo sempre venha populado no show (ao contrário do index).

Erros

StatusSituação
401Token inválido ou ausente
404Estudo não encontrado, ou pertence a outro tenant/unit

GET /api/studies//series

Lista as séries de um estudo. Auth: auth:api

Response 200

Array (sem paginação):
[
  {
    "id": "uuid",
    "study_id": "uuid",
    "orthanc_series_id": "string",
    "series_instance_uid": "string",
    "modality": "string",
    "series_number": 1,
    "manufacturer": "string | null",
    "instance_count": 256,
    "created_at": "iso8601",
    "updated_at": "iso8601"
  }
]
Ordenação: series_number ASC, created_at ASC.

Erros

StatusSituação
404Estudo não encontrado ou fora do tenant/unit

GET /api/series//instances

Lista as instâncias (imagens) de uma série. Auth: auth:api

Response 200

[
  {
    "id": "uuid",
    "series_id": "uuid",
    "orthanc_instance_id": "string",
    "sop_instance_uid": "string",
    "instance_number": 1,
    "rows": 512,
    "columns": 512,
    "slice_thickness": 1.25,
    "created_at": "iso8601",
    "updated_at": "iso8601"
  }
]
Ordenação: instance_number ASC, created_at ASC.

GET /api/studies//instances//rendered

Retorna a imagem renderizada (JPEG) de uma instância, via proxy para o Orthanc. Auth: auth:api

Response 200

  • Content-Type: image/jpeg (propagado do Orthanc)
  • Body: binário da imagem
  • Headers: Cache-Control: no-cache, private

Erros

StatusSituaçãoBody
404Estudo/instância não existe, ou Orthanc retornou erro{"message": "Image not available"}

Notas

  • Timeout de 20s na chamada ao Orthanc
  • Usado pelo frontend para preview de imagens individuais (ex.: seleção de frames para exportar no PDF)

GET /api/studies//thumbnail

Thumbnail do estudo (JPEG 300×300). Auth: auth:api

Response 200

  • Content-Type: image/jpeg
  • Body: binário (arquivo thumbnails/{orthanc_study_id}/preview.jpg no volume pacs_storage)
  • Headers: Cache-Control: no-cache, private

Erros

StatusSituaçãoBody
404Thumbnail ainda não gerado pelo worker{"message": "Thumbnail not ready"}

GET /api/studies//series//thumbnail

Thumbnail de uma série específica. Auth: auth:api

Response 200

  • Content-Type: image/jpeg
  • Body: binário
  • Headers: Cache-Control: no-cache, private
  • Fallback: se o thumbnail da série (thumbnails/{orthanc_study_id}/series/{orthanc_series_id}.jpg) não existir, retorna o do estudo (thumbnails/{orthanc_study_id}/preview.jpg)

Erros

StatusSituaçãoBody
404Nenhum thumbnail disponível (série nem estudo){"message": "Thumbnail not ready"}