G2I — Ficha de Integração
Integração outbound com o sistema G2I: a Public API envia status de assinatura do exame (redirect) e, em fluxo separado, notifica comentário + status (notify) ao endpoint configurado no cliente.
:::info Classificação
- T2 (outbound): adapter
g2iemPOST /exam/redirect(acao=REDIRECT) ePOST /exam/notify(acao=NOTIFY) — Mobilemed envia payload aourldetb_integracao_config. - T1 (inbound): não se aplica — não há rota gateway específica G2I no código. :::
Identificação
| Campo | Valor |
|---|---|
| Tipo | T2 (adapter outbound) |
adapter_key | g2i |
| Classe | adapters/G2IAdapter.js |
| Cliente/tenant | Multi-tenant (configurado por tb_integracao) |
| Status | ativo |
| Owner squad | Tais Oliveira |
| Contato técnico cliente | rodrigo@grupog2i.com.br, alex@grupog2i.com.br, gustavo.coutinho@grupog2i.com.br |
| Última revisão | 2026-09-22 |
Escopo
Fluxo completo
Rotas envolvidas
| Direção | Método | Rota | acao (middleware) | Função |
|---|---|---|---|---|
| Outbound | POST | /exam/redirect | REDIRECT | Monta { accessionNumber, isSigned } e envia ao url do adapter g2i |
| Outbound | POST | /exam/notify | NOTIFY | Busca último comentário do exame e envia { comment, status } ao url |
| Outbound | POST | /exam/notifyUpdate | NOTIFY_UPDATE | Mesmo handler notify do controller; exige config com acao=NOTIFY_UPDATE se usada |
O adapter implementa apply() e notify(). Não há override de getRequests, convertUrlVariable nem _validateToken.
:::caution OpenAPI
Não existe path /exam/g2i (nem equivalente) em swaggerDocs.json. Os contratos HTTP do gateway são os genéricos Integra exame (POST /exam/redirect) e Envia notificação de exame (POST /exam/notify).
:::
Ambientes
| Ambiente | Base URL |
|---|---|
| Homologação | https://gateway-homolog.mobilemed.com.br/api-public |
| Produção | https://integracao.mobilemed.com.br/v1 |
Headers obrigatórios no gateway: token, api (mob ou one).
Configuração (banco)
Registros em tb_integracao + tb_integracao_config (models/IntegrationConfig.js). Em geral são duas configs (ou mais), uma por acao.
| Campo | Valor típico | Observação |
|---|---|---|
adapter | g2i | Deve bater com adapters/index.js |
acao | REDIRECT e/ou NOTIFY | Middleware: /exam/redirect → REDIRECT; /exam/notify → NOTIFY. Opcional: NOTIFY_UPDATE para /exam/notifyUpdate |
url | URL do endpoint G2I do cliente | G2IAdapter não implementa convertUrlVariable; URL com [#variable#] falharia no service |
reportFormat | qualquer ENUM válido | Não usado pelo G2IAdapter (payload não inclui corpo de laudo) |
tipo_envio | JSON | Payload é objeto JS; service envia como JSON quando tipo_envio === "JSON" |
base64 | irrelevante para este adapter | Não há conversão de laudo no adapter |
auth_type | TOKEN, BASIC_AUTH ou DEFAULT | Ver seção Autenticação — comportamento diferente entre redirect e notify |
automatic_retry | conforme tb_integracao | Usado pelo RetryService no fluxo de redirect |
additional_settings.alternativeMethod | ex. "put" | Método HTTP alternativo no externalRequest (fluxo genérico) |
additional_settings.redirectConditionals | objeto condicional | Só no fluxo redirect() — pode lançar BLOCKED_BY_CONFIG |
additional_settings.validateToken | se aplicável | Chama _validateToken do adapter antes do envio (G2I não implementa o método) |
additional_settings.notificarEnvioComentario | true | Portal-API (verificaNotifyUpdate): com acao=NOTIFY_UPDATE, ao adicionar comentário dispara o emit de notify |
headers_adicionais | JSON em tb_integracao | Headers extras no POST outbound |
:::info Pré-requisito de laudo (redirect e notify assinados)
Mesmo sem converter laudo, o fluxo genérico de redirect() exige study.laudo.pdf_path (tenta reprocessar; senão lança erro). Em notify(), se status_id for 1 ou 5 e não houver pdf_path, também lança erro antes de chamar o adapter.
:::
Autenticação
Inbound (gateway → Mobilemed)
| Header | Obrigatório | Descrição |
|---|---|---|
token | sim | Token da integração (tb_integracao.token) |
api | sim | Ambiente: mob ou one |
Outbound (Mobilemed → G2I)
POST /exam/redirect → exam.service.js → redirect()
Usa integration.config.auth_type (com fallback DEFAULT para credenciais de tb_integracao):
auth_type (config ou integração) | Comportamento |
|---|---|
TOKEN + token_name | Header dinâmico: {token_name}: {client_token} |
BASIC_AUTH | Header Authorization: Basic {base64(user:pass)} |
DEFAULT | Herda auth_type / credenciais de tb_integracao |
POST /exam/notify → exam.service.js → notify()
Usa somente integration.auth_type de tb_integracao (não lê config.auth_type):
auth_type (tb_integracao) | Comportamento |
|---|---|
TOKEN + token_name | Header {token_name}: {client_token} |
BASIC_AUTH | Header Authorization: Basic {base64(user:pass)} |
Credenciais adicionais podem ser injetadas via headers_adicionais (JSON) em ambos os fluxos.
Rotação de credenciais: a confirmar (responsável / data).
Contrato
Inbound
Não se aplica.
Outbound — POST /exam/redirect → G2IAdapter.apply()
Payload montado pelo adapter e enviado ao url:
json{"accessionNumber": "2026001001","isSigned": true}
| Campo | Regra no código |
|---|---|
accessionNumber | study.pacs_accession_no |
isSigned | true se status_id === 1 ou status_id === 5; caso contrário false |
O adapter ignora integration, reportOptions e env em apply() (assinatura efetiva: apply(_, study)).
Outbound — POST /exam/notify → G2IAdapter.notify()
Antes de montar o payload, o adapter:
- Instancia
CommentService(env)e busca o último comentário (ExameComentarioordenado porid DESC). - Se a busca falhar, registra log de integração tipo 52 com mensagem
G2I: erro ao buscar último comentário...e segue comcommentvazio. - Se não houver comentário,
commentfica"".
json{"comment": "Texto do último comentário do exame","status": 1}
| Campo | Regra no código |
|---|---|
comment | comment.descricao do último ExameComentario, ou "" |
status | study.status_id (número) |
_integration e _anexoID são recebidos mas não usados pelo adapter.
Erros comuns (outbound)
| Erro | Causa |
|---|---|
Erro ao redirecionar exame devido a laudo ainda não processado | Laudo sem pdf_path no fluxo genérico de redirect() |
Erro ao notificar devido a laudo ainda não processado | status_id 1 ou 5 sem pdf_path no fluxo genérico de notify() |
BLOCKED_BY_CONFIG | Bloqueio por redirectConditionals em additional_settings (só redirect) |
404 No integration found | Token inválido/inativo ou config com acao correspondente ausente |
adapter.convertUrlVariable is not a function | url contém [#variable#] e o G2IAdapter não implementa o método |
| Log tipo 52 (não aborta o notify) | Falha ao buscar último comentário — payload segue com comment: "" |
Idempotência / retry
- Exames com
status_id = 5passam pela lógica de retentativa (RetryService) no controllerredirect. automatic_retryemtb_integracaocontrola retentativas automáticas no redirect.- Payloads são determinísticos para o mesmo estado do exame (sem ID aleatório) — reenvio com o mesmo status/comentário produz o mesmo corpo.
- O fluxo
notifynão usaRetryServiceno trecho lido do controller.
Operação
| Item | Detalhe |
|---|---|
| Código adapter | mm-pacs-public-api/adapters/G2IAdapter.js |
| Registro da chave | adapters/index.js → g2i: G2IAdapter |
| Controller outbound | controllers/exam.controllers.js → redirect, notify |
| Service outbound | services/exam.service.js → redirect(), notify() |
| Comentários (notify) | services/comment.service.js → getLastComment() |
| Logs de falha de comentário | services/log.service.js (tipo 52) |
| Deploy / runbook | a confirmar |
| Monitoramento | Logs de integração no redirect/notify (tipo 42 no controller); tipo 52 em falha de comentário G2I |
| Escalação | a confirmar |
Evidências
Homologação com dados de teste (sem PHI de paciente real).
Configuração no Portal — acao=REDIRECT
Sistema Teste G2I, adapter g2i, autenticação Default, envio JSON, URL de webhook de teste. additional_settings: {"notificarEnvioComentario":true}.

Redirect — payload outbound
Corpo enviado ao cliente (G2IAdapter.apply()):
json{"accessionNumber": "123123123123123123123123123123","isSigned": true}

Notify — payload outbound
Corpo enviado ao cliente (G2IAdapter.notify()), comentário de teste:
json{"comment": "tatatat","status": 0}
Rastreio
| Item | Valor |
|---|---|
| Tarefa Bitrix | https://mobilemed.bitrix24.com.br/company/personal/user/1970/tasks/task/view/62318/ |
| PR código | Public-API: develop #443, master #441 Portal-API: develop #782, master #780 |
| PR documentação | develop #57, main #55 |
| URL publicada | /docs/interfaceReference/integrations/g2i |
| Ficha no repo | docs/interfaceReference/integrations/g2i/index.md |