HL7 MLLP Gateway

Entre com as credenciais configuradas no servidor.

HTTP-
Destino MLLP-
Listener P05-
Webhook-

Monitor

Enviados hoje0
Laudos recebidos0
ACK AA0%
Falhas hoje0

Eventos recentes

Data/Hora Direção Tipo Paciente Accession Controle ACK ms

Histórico persistido

Data/Hora Direção Tipo Origem Paciente Accession ACK ms Webhook

Formulário P01

MSH
PID
IN1 / ORC
Como testar ORC-1:
  • NW — Novo pedido. Use um placerOrder e accession novos para o paciente.
  • XO — Alteração. Reaproveite placerOrder/accession de um pedido já enviado e altere algum atributo (data, descrição, prioridade).
  • CA — Cancelamento. Mantenha placerOrder/accession originais do pedido a cancelar.
Campos gerados / constantes
OBX (observação clínica)

Exemplo carregado de /api/layouts/worklist.json.

Layouts de integração

Envio de exame P01

POST /hl7/send aceita HL7 bruto, HL7 com frame MLLP ou JSON estruturado. Quando recebe JSON, o gateway valida os campos e monta uma mensagem ORM^O01 HL7 2.4 antes de encaminhar ao destino MLLP.

O payload original (HL7 ou JSON) é preservado no evento e pode ser baixado em GET /api/events/:id/download?kind=raw.

Obtenção de laudos P05

O PACS/Mirth envia ORU^R01 para o listener MLLP local em REPORT_MLLP_HOST/REPORT_MLLP_PORT. O gateway grava o evento, responde ACK e, se houver webhook configurado, encaminha o laudo para a aplicação de terceiro.

O HL7 do laudo é preservado no evento e pode ser baixado individualmente como .hl7, .ack, JSON técnico ou payload original. Se o payload original for idêntico ao HL7 normalizado, o evento persiste apenas message e o download raw usa esse fallback.

Contrato JSON de worklist P01

Os layouts baixados usam o mesmo exemplo canônico de /api/layouts/worklist.json. Campos constantes ou derivados aparecem separadamente para evitar edição indevida.

MSH / PID

Atributo Obrigatório Referência HL7 Exemplo Descrição
msh.sendingApplication Sim MSH-3.1 RISAPP Aplicação remetente.
msh.sendingFacility Sim MSH-4.1 RISFAC Fornecedor ou instalação remetente.
msh.receivingApplication Sim MSH-5.1 PIXEON Aplicação receptora, normalmente Pixeon.
msh.receivingFacility Sim MSH-6.1 MEDREPORT Facilidade receptora.
msh.dateTime Não MSH-7.1 20191012173000 Data/hora da mensagem. Se vazio, o gateway gera automaticamente.
msh.messageControlId Não MSH-10.1 6467855 ID único da mensagem. Se vazio, o gateway gera automaticamente.
msh.processingId Sim MSH-11.1 P Identificação do processo.
msh.version Sim MSH-12.1 2.4 Versão HL7 suportada pelo gateway.
patient.id Sim PID-3.1 25200 Código interno do paciente.
patient.cpf Não PID-3.2 00032145690 CPF do paciente.
patient.rg Não PID-3.3 3024678798 RG do paciente.
patient.familyName Sim PID-5.1 PIXEON Sobrenome.
patient.givenName Sim PID-5.2 PACIENTE Primeiro nome.
patient.middleName Não PID-5.3 DE TESTE Nome do meio.
patient.suffix Não PID-5.4 FILHO Sufixo do nome do paciente.
patient.prefix Não PID-5.5 SR Prefixo do nome do paciente.
patient.preferredName Não PID-5.15 PACIENTE SOCIAL Nome social.
patient.birthDate Sim PID-7.1 19830824 Data de nascimento em yyyyMMdd.
patient.sex Sim PID-8.1 M Aceita F, M, O ou U.
patient.phone Não PID-13.1 (99) 99999-9999 Telefone do paciente.
patient.email Não PID-13.4 paciente@email.com E-mail do paciente.

IN1 / ORC

Atributo Obrigatório Referência HL7 Exemplo Descrição
insurance.planId Não IN1-2.1 15 ID do plano.
insurance.planName Não IN1-2.2 PLANO DE SAUDE Nome do plano.
insurance.companyId Não IN1-3.1 5 ID do convênio.
insurance.companyName Não IN1-4.1 CONVENIO Nome do convênio.
order.control Sim ORC-1.1 NW NW novo, XO alteração, CA cancelamento.
order.placerOrder Sim ORC-2.1 1437 Número da requisição. Também alimenta OBR-2.1.
order.transactionDate Sim ORC-9.1 20191012153000 Data/hora do atendimento em yyyyMMddHHmmss.
order.location Não ORC-13.1 PRONTO SOCORRO Setor solicitante.
order.room Não ORC-13.2 12A Quarto ou enfermaria.
order.department Não ORC-17.1 TRAUMATOLOGIA Unidade solicitante. Chave JSON mantida por compatibilidade.
order.facilityName Não ORC-21.1 HOSPITAL XYZ Instituição solicitante.

OBR / OBX

Atributo Obrigatório Referência HL7 Exemplo Descrição
exams[].code Sim OBR-4.1 20 Código identificador do exame.
exams[].priority Não OBR-5.1 R R rotina ou U urgente.
exams[].description Sim OBR-15.3 RAIO-X TORAX Descrição do procedimento.
exams[].bodySite Não OBR-15.4 TORAX Região do corpo.
exams[].requestingDoctorFamilyName Não OBR-16.2 SOLICITANTE Sobrenome do médico solicitante.
exams[].requestingDoctorGivenName Não OBR-16.3 MEDICO Primeiro nome do médico solicitante.
exams[].requestingDoctorMiddleName Não OBR-16.4 DO Nome do meio do médico solicitante.
exams[].requestingDoctorSuffix Não OBR-16.5 FILHO Sufixo do médico solicitante.
exams[].requestingDoctorPrefix Não OBR-16.6 DR Prefixo do médico solicitante.
exams[].doctorPhone Não OBR-17.1 (88) 88888-8888 Telefone do médico solicitante.
exams[].doctorEmail Não OBR-17.4 solicitante@email.com E-mail do médico solicitante.
exams[].accession Não OBR-18.1 14371 Identificador do item do atendimento.
exams[].requesterCrm Não OBR-19.1 1234 CRM do médico solicitante.
exams[].requesterCrmUf Não OBR-19.2 SC UF do CRM do médico solicitante.
exams[].radiologistCrm Não OBR-20.1 6789 CRM do médico radiologista.
exams[].radiologistCrmUf Não OBR-20.2 SC UF do CRM do médico radiologista.
exams[].webProtocol Não OBR-21.1 protocolo Protocolo de acesso web do exame.
exams[].webPassword Não OBR-21.2 senha Senha de acesso web do exame.
exams[].expectedReportAt Não OBR-22.1 20191013120000 Results rpt/status chng > Date/Time. Data prevista de entrega do laudo.
exams[].modality Não OBR-24.1 CR Modalidade do exame.
exams[].performedAt Sim OBR-27.4 20191012153000 Data/hora da realização.
exams[].radiologistFamilyName Não OBR-32.1 RADIOLOGISTA Sobrenome do radiologista responsável.
exams[].radiologistGivenName Não OBR-32.1 NOME Primeiro nome do radiologista responsável.
exams[].radiologistMiddleName Não OBR-32.1 NOME DO MEIO Nome do meio do radiologista responsável. No HL7 final usa & como separador.
clinicalObservation Não OBX-5.1 Teste OBX HL7 Observação clínica. O gateway codifica o texto em Base64 no HL7 gerado.

Campos gerados / constantes do gateway

Campo HL7 Origem Valor Comportamento
MSH-1 Constante | Separador de campos fixo.
MSH-2 Constante ^~\& Encoding characters fixos.
MSH-9 Constante ORM^O01 Tipo da mensagem P01 enviada pelo gateway.
OBR-1 Derivado 1..N Set ID sequencial por exame.
OBR-2 Derivado order.placerOrder Replicado em todos os segmentos OBR.
OBX-1 Constante 1 Usado quando houver observação clínica.
OBX-5 Derivado Base64(clinicalObservation) Texto puro convertido para Base64 antes do envio.

Layout P05 ORU^R01

Campo HL7 Exemplo Descrição
MSH-9 ORU^R01 Tipo da mensagem de laudo.
MSH-10 74178909012 Identificador único da mensagem ORU.
PID-3.1 185968 Patient ID.
PID-5.1 JOSE DA SILVA OLIVEIRA Nome completo do paciente.
ORC-1.1 RE Order control do retorno.
ORC-3.1 1029177 Accession number.
ORC-5.1 CM Status do laudo.
OBR-1.1 1 Set ID do segmento OBR.
OBR-3.1 1029177 Accession number repetido no OBR.
OBX-1.1 0..6 Ordem de concatenação dos fragmentos do laudo.
OBX-3.1 1029177 Accession number do laudo.
OBX-4.1 2443 ID do laudo ou sub-ID de observação.
OBX-5.1 {\E\rtf1...} Fragmento RTF do laudo, preservado para concatenação.
OBX-14.1 20111026094610 Data/hora da observação.

Layout P05 ACK

Campo HL7 Exemplo Descrição
MSH-3.1 RISAPP Aplicação remetente da resposta.
MSH-4.1 RISFAC Facilidade remetente da resposta.
MSH-5.1 PIXEON Aplicação receptora da resposta.
MSH-6.1 MEDREPORT Facilidade receptora da resposta.
MSH-9 ACK Tipo da mensagem de confirmação.
MSH-10 7890 Message Control ID da resposta.
MSH-11 p Processing ID do ACK.
MSH-12 2.4 Versão HL7 do ACK.
MSA-1 AA Código do ACK: AA, AR ou AE.
MSA-2 1234 Message Control ID da mensagem respondida.
MSA-3 OK Texto do ACK ou da falha.

Configuração do webhook

As alterações são persistidas em data/webhook.json e passam a valer imediatamente, sobrepondo o .env.

Payload JSON enviado ao webhook

{
  "eventId": "uuid",
  "receivedAt": "ISO-8601",
  "messageType": "ORU^R01^ORU_R01",
  "summary": {
    "messageType": "ORU^R01^ORU_R01",
    "messageControlId": "...",
    "patientName": "...",
    "patientId": "...",
    "accession": "...",
    "reportId": "...",
    "obxCount": 3,
    "orderControl": "RE",
    "orderStatus": "CM",
    "obrCount": 1,
    "partCount": 1,
    "contentKind": "rtf"
  },
  "patient": {
    "id": "...",
    "name": "..."
  },
  "order": {
    "control": "RE",
    "status": "CM",
    "accession": "..."
  },
  "content": {
    "kind": "rtf",
    "mimeType": "application/rtf",
    "reportCount": 1
  },
  "reports": [
    {
      "accession": "...",
      "reportId": "...",
      "observedAt": "YYYYMMDDHHMMSS",
      "orderControl": "RE",
      "orderStatus": "CM",
      "fragments": {
        "count": 3,
        "setIds": [0, 1, 2]
      },
      "professionals": {
        "technician": {
          "crm": "11034",
          "uf": "GO",
          "name": "Leandra Pereira da Silva Costa"
        }
      },
      "performedAt": "YYYYMMDDHHMMSS",
      "performedEndedAt": "YYYYMMDDHHMMSS",
      "reportStatusChangedAt": "YYYYMMDDHHMMSS",
      "reportStatus": "F",
      "quantityTiming": "...",
      "content": {
        "kind": "rtf",
        "mimeType": "application/rtf",
        "sourceEncoding": "plain",
        "rtf": "{\\rtf1\\ansi...}",
        "text": "Texto higienizado do laudo"
      }
    }
  ]
}

No P05, accession e o identificador canonico do pedido/laudo. Os aliases internos orderId, placerOrder e fillerOrder nao fazem parte deste POST.

Os profissionais responsáveis pelo laudo ficam em reports[].professionals, sem duplicar os campos já presentes no contrato. Conforme HL7 v2.3.1, são tratados OBR-32 (interpretador principal), OBR-33 (assistente), OBR-34 (técnico) e OBR-35 (transcritor).

Quando preenchidos, OBR-7, OBR-8, OBR-22 e OBR-25 são enviados como performedAt, performedEndedAt, reportStatusChangedAt e reportStatus, respectivamente.

OBR-27 é enviado como quantityTiming, conforme o padrão, sem assumir que um valor do fornecedor nessa posição seja a data de liberação.

O conteúdo dentro de reports[].content é controlado por WEBHOOK_CONTENT. O gateway envia somente a representação útil de cada parte: rtf, text ou base64.

Para anexos binários, como PDF em Base64, o item terá content.kind="pdf" e o binário ficará apenas em reports[].content.base64. Em cancelamentos ou correções com OBX-5 vazio, os metadados do laudo continuam presentes com content.kind="none".

Significado dos atributos do webhook

Esta aba documenta o contrato JSON quando WEBHOOK_FORMAT=json. Campos opcionais podem ser omitidos quando não houver valor aplicável.

Campos de topo

Atributo Significado Valores / formato
eventId Identificador único do evento persistido no gateway. UUID.
receivedAt Data/hora em que o gateway recebeu o laudo. ISO-8601 UTC.
messageType Valor do MSH-9 recebido. Normalmente ORU^R01 ou ORU^R01^ORU_R01.
summary Resumo curto do laudo, usado para filtro e auditoria. Objeto. Ver tabela abaixo.
patient Dados do paciente extraídos do PID. Objeto com id e name.
order Identificadores e status do pedido/laudo. Objeto. Ver tabela abaixo.
content Resumo global do tipo de conteúdo encontrado. Objeto com kind, mimeType e reportCount.
reports Lista de partes do laudo agrupadas por accession + reportId. Array. Cada item representa uma parte lógica.

summary

Atributo Significado Valores / formato
summary.messageType Espelho do tipo HL7 recebido. ORU^R01 ou ORU^R01^ORU_R01.
summary.messageControlId Identificador da mensagem HL7. Valor de MSH-10.
summary.patientId Identificador principal do paciente. Valor de PID-3.1.
summary.patientName Nome do paciente em formato legível. Texto derivado de PID-5.
summary.accession Identificador canonico do pedido/laudo no P05. ORC-3, com fallback para OBR-3 ou OBX-3 quando necessario.
summary.reportId ID principal do laudo/parte. Normalmente OBX-4.
summary.reportIds Lista de IDs quando houver múltiplas partes. Array opcional de strings.
summary.obxCount Total de segmentos OBX recebidos. Inteiro >= 0.
summary.orderControl Ação do pedido/laudo. Valor de ORC-1. Exemplos: RE (resultado), CA (cancelamento), XO (alteração/correção).
summary.orderStatus Status do pedido/laudo. Valor de ORC-5. Exemplos: CM (final), A (parcial), ou outro valor enviado pela origem.
summary.obrCount Total de segmentos OBR recebidos. Inteiro >= 0.
summary.partCount Total de partes lógicas em reports[]. Inteiro >= 0.
summary.contentKind Tipo global/predominante do conteúdo do laudo. rtf, pdf, text, binary, none ou mixed.

patient e order

Atributo Significado Valores / formato
patient.id ID principal do paciente. Texto derivado de PID-3.1.
patient.name Nome do paciente em formato legível. Texto derivado de PID-5.
order.control Mesmo significado de summary.orderControl. RE, CA, XO, etc.
order.status Mesmo significado de summary.orderStatus. CM, A ou outro código enviado.
order.accession Identificador canonico do pedido/laudo no P05. String nao vazia quando o accession for informado.

content e reports[]

Atributo Significado Valores / formato
content.kind Resumo global do tipo de conteúdo encontrado nas partes. rtf, pdf, text, binary, none ou mixed.
content.mimeType MIME type consolidado quando houver um único tipo. application/rtf, application/pdf, text/plain; charset=utf-8, application/octet-stream ou vazio.
content.reportCount Quantidade de itens presentes em reports[]. Inteiro >= 0.
reports[].accession Accession/filler order daquela parte. String.
reports[].reportId ID da parte/laudo daquela entrada. String.
reports[].observedAt Data/hora observada para a parte. Normalmente OBX-14 em YYYYMMDDHHMMSS.
reports[].orderControl Ação associada àquela parte. RE, CA, XO, etc.
reports[].orderStatus Status associado àquela parte. CM, A ou outro código enviado.
reports[].fragments.count Quantidade de segmentos OBX usados na parte. Inteiro >= 0.
reports[].fragments.setIds Ordem dos fragmentos concatenados. Array de inteiros. Ex.: [0,1,2].
reports[].content.kind Tipo real do conteúdo daquela parte. rtf, pdf, text, binary ou none.
reports[].content.mimeType MIME type específico da parte. application/rtf, application/pdf, text/plain; charset=utf-8, application/octet-stream ou vazio.
reports[].content.sourceEncoding Como o conteúdo chegou ao gateway. plain (texto/RTF em claro), base64 (PDF/RTF/binário codificado) ou none.
reports[].content.rtf RTF recomposto da parte. String opcional. Sai quando aplicável e permitido por WEBHOOK_CONTENT.
reports[].content.text Versão textual higienizada do conteúdo. String opcional. Sai quando derivável e permitido por WEBHOOK_CONTENT.
reports[].content.base64 Conteúdo binário/original em Base64. String opcional. Usado principalmente para pdf ou binário.

Influência de WEBHOOK_CONTENT

Configuração O que o cliente recebe
original Apenas a forma original útil da parte: rtf, base64 ou text.
sanitized Apenas text quando o gateway conseguir derivá-lo.
both Forma original e também text quando aplicável.
none Somente metadados; os campos rtf, text e base64 são omitidos.

Entregas do webhook

Data/Hora Event ID HTTP OK ms Bytes Erro

Rotas HTTP

Rota Uso

Configurações

Variável Descrição
HTTP_HOST / HTTP_PORT Host e porta da interface/API HTTP.
API_KEY Quando definida, exige x-api-key ou Authorization: Bearer.
UI_USER / UI_PASSWORD Credenciais fixas para a tela de login. Se vazias, login é desabilitado.
CORS_ORIGIN Origens permitidas.
HTTP_BODY_LIMIT_BYTES Limite de payload HTTP.
MIRTH_HOST / MIRTH_PORT Destino MLLP para envio P01.
MIRTH_CONNECT_TIMEOUT_MS / MIRTH_RESPONSE_TIMEOUT_MS Timeouts do cliente MLLP.
MLLP_EXPECT_ACK Se o envio espera ACK antes de responder.
REPORT_MLLP_ENABLED Ativa/desativa listener MLLP para laudos.
REPORT_MLLP_HOST / REPORT_MLLP_PORT Host e porta do listener P05.
REPORT_STORE_LIMIT Quantos laudos manter em memória.
DATA_DIR Diretório para events/YYYY-MM-DD.jsonl, logs/YYYY-MM-DD.log e webhook.json.
EVENT_STORE_LIMIT Eventos mantidos em memória.
LOG_STDOUT Emite logs sanitizados no stdout.
ACK_* / REPORT_AUTO_ACK_* Dados do ACK de resposta P05.
WEBHOOK_URL URL para POST automático dos laudos recebidos.
WEBHOOK_FORMAT json ou hl7.
WEBHOOK_CONTENT original, sanitized, both ou none.
WEBHOOK_AUTH_HEADER Header de autenticação opcional.
WEBHOOK_TIMEOUT_MS Timeout do POST do webhook.

Exemplos de resposta

Persistência

  • Eventos enviados/recebidos: data/events/YYYY-MM-DD.jsonl, uma linha JSON por evento, contendo HL7, ACK e o payload original (raw HL7 ou JSON enviado pelo terceiro).
  • Logs técnicos sanitizados: data/logs/YYYY-MM-DD.log.
  • Configuração editada pela aba Webhook: data/webhook.json.
  • Para download de arquivos .hl7 individuais use a aba Monitor/Eventos ou a API /api/events/:id/download.

Segurança e operação

  • Use UI_USER+UI_PASSWORD para proteger a interface.
  • Use API_KEY em homologação/produção. Sem TLS e sem restrição de rede, não exponha o gateway publicamente.
  • Persista DATA_DIR em volume Docker para manter histórico.
  • Cada evento recebe um eventId único para auditoria e download.