Webhooks
Receba eventos e adapte as notificações ao seu sistema.
Configure em Admin → Unidades → Tokens de API → Webhook de retorno.
| Evento | Quando é gerado |
|---|---|
report.signed |
Assinatura, retificação ou recebimento externo do laudo |
study.received |
Primeiro estudo estável disponibilizado ao RIS, após a janela sem novas imagens |
É possível selecionar os eventos, definir os destinos, configurar autenticação por header e adaptar o JSON enviado. A prévia utiliza dados sintéticos e não chama o sistema de destino.
O receptor confirma o recebimento com HTTP 2xx. Há timeout de 10 segundos e até seis novas tentativas, em 2, 4, 8, 16, 32 e 64 minutos. O corpo preparado permanece igual nas repetições; o receptor deve tratar entregas repetidas sem duplicar sua operação.
O template usa a representação padrão do laudo, com URL quando disponível. Ele não carrega o PDF em base64 nem anexos binários. SOAP, outras formas de autenticação ou transporte e mensagens que exigem binários embutidos podem precisar de um conector específico.
Ativar um evento não envia retroativamente todos os exames antigos. A reintegração manual disponível é exclusiva de laudos. Os logs da credencial ajudam a acompanhar chamadas recebidas e tentativas de entrega.
Eventos e destinos
report.signed: assinatura, retificação e recebimento externo do laudo, nos mesmos pontos do callback anterior. A reintegração manual continua exclusiva de laudos.study.received: primeirostudy-stabledisponibilizado ao RIS, após a janela de 60 segundos sem novas imagens. Não exige laudo. É uma notificação por organização/credencial/StudyInstanceUID, não por instância DICOM.- Exames cancelados não geram entregas. Um exame já laudado pode receber seu primeiro vínculo DICOM sem alteração do estado do laudo. Um UID diferente não substitui o vínculo de um exame laudado/atribuído.
webhookUrlStudy: nullusa a URL de laudo, escolha explícita no formulário. Sem destino efetivo não há entrega.- Assinaturas de evento são avaliadas na geração. Alterar URL/autenticação afeta entregas pendentes; apagar o destino ou revogar a credencial interrompe a entrega. Template e corpo seguem o snapshot descrito abaixo.
O registro durável mobilemed_study_receipts guarda o primeiro estudo estável inclusive sem assinantes. Ativar a assinatura depois não faz uma onda posterior entregar retroativamente o recebimento. Esse histórico começa no primeiro study-stable processado após instalar a funcionalidade: não inventamos o histórico anterior. UID já vinculado por study-started não significa que o primeiro study-stable já ocorreu. A transação do consumidor grava recibo e entregas conjuntamente; rollback permite tentar novamente. A unicidade inclui registros logicamente excluídos.
API administrativa
PATCH /api/v1/units/:unitId/api-clients/:clientId
{
"webhookEvents": ["report.signed", "study.received"],
"webhookUrlReport": "https://sistema.exemplo/laudos",
"webhookUrlStudy": "https://sistema.exemplo/imagens",
"webhookPayloadTemplates": {
"report.signed": {
"evento": {"$path": ["event"]},
"numero": {"$path": ["study", "accessionNumber"]},
"resultado": {"$path": ["study", "report", "content"]},
"origem": {"$literal": "Themis"}
},
"study.received": {
"pedido": {"$path": ["source", "pedido", "numero"], "$default": null},
"estudo": {"$path": ["study", "studyUID"]}
}
}
}
GET da lista de credenciais e resposta do PATCH incluem os três campos novos. Omissão preserva; webhookEvents:null restaura ["report.signed"], [] desliga novos eventos; webhookPayloadTemplates:null restaura {}. A URL nula limpa o destino específico. webhookAuthHeaderName/webhookAuthHeaderValue mantêm o contrato anterior: valor omitido ou vazio preserva; valor nulo remove. Remover o nome do header remove também seu valor. A resposta contém apenas webhookConfigured e o nome, nunca o valor cifrado ou decifrado.
POST /api/v1/units/:unitId/api-clients/:clientId/webhook-preview responde 200 { "payload": <JSON> }, sem chamada externa ou leitura de exames reais:
{
"event": "study.received",
"template": {"ativo": {"$path": ["source", "ativo"]}},
"context": {"source": {"ativo": false}}
}
template omitido usa o template salvo; template:null produz JSON null. useDefaultTemplate:true permite visualizar o formato padrão ao remover um template no editor. context é opcional e aceita somente study, source, eventId, occurredAt e sentAt, até 65536 bytes de JSON UTF-8. O evento sempre vem de event. Sem contexto usam-se dados fictícios estáveis. A UI mostra a prévia sintética, permite salvar e reabrir os valores.
Linguagem de templates
Objetos, arrays e valores JSON nativos são aceitos, inclusive na raiz (false, 0, "", null). A ausência da chave do evento no mapa escolhe o formato padrão; um valor falso ou nulo configurado nunca significa ausência.
{"$path":["study","report","content"]}preserva o tipo do valor; segmentos numéricos acessam índices de arrays.- Caminho ausente resulta em
null;$defaultfornece um literal alternativo. Valores existentesfalse,0,""enullsão preservados. {"$literal": ...}inclui JSON literalmente, sem interpretar suas chaves.- Raízes disponíveis:
event,eventId,occurredAt,sentAt,study,source. - Limites: mapa de templates de 65536 bytes UTF-8, profundidade 20, caminhos de 1 a 20 segmentos, segmentos de texto até 128 caracteres. Chaves especiais desconhecidas, raízes não permitidas e acesso a protótipos são recusados. Não há código, interpolação executável, loops nem chamadas externas.
study usa o perfil atual da credencial: IDs públicos numéricos para MobileMed, compatibilidade anterior no perfil legacy. O conteúdo do laudo usa a visão padrão da API (URL quando disponível), sem carregar PDF/base64 ou anexos binários. source é o objeto JSON/XML parseado do ingresso PROJECTED mais recente desse mesmo cliente e item; exclui ingressos deletados e não cruza credenciais. Reprocessamento não reordena ingressos. Só é consultado quando o template pode referenciá-lo.
Persistência e retry
Na geração ficam imutáveis: evento, UUID do evento, data de ocorrência no RIS, item, UID, versão da linguagem (1) e envelope do template {configured,value}. Na primeira preparação o worker resolve study/source e grava o corpo HTTP exato por compare-and-set. Repetições reutilizam esses mesmos bytes, incluindo sentAt, mesmo que o exame, ingresso ou template mude. SQL NULL significa não preparado; o texto null é um corpo JSON já preparado. URLs contidas no corpo mantêm a validade original; o snapshot não renova links durante retries.
As tentativas antigas sem metadados continuam no caminho de compatibilidade anterior. Sem template, novas tentativas mantêm a estrutura anterior {event,sentAt,study}. O destino e a autenticação de transporte são consultados a cada tentativa, permitindo rotação do segredo. O backoff existente e a reintegração manual de laudos permanecem.