TOTVS — Ficha de Integração
Integração bidirecional com o ecossistema TOTVS: recebimento de pedidos via gateway e devolução de laudos ao RIS do cliente via adapter outbound.
Referência OpenAPI — POST /exam/redirect:::info Classificação
- T1 (inbound):
POST /exam/pedido/totvs— TOTVS envia pedidos à Mobilemed. - T2 (outbound): adapter
totvsemPOST /exam/redirect— Mobilemed envia laudo ao endpoint configurado emtb_integracao_config.url. :::
Identificação
| Campo | Valor |
|---|---|
| Tipo | T2 (adapter outbound) + rota inbound específica |
adapter_key | totvs |
| Classe | adapters/TotvsAdapter.js |
| Cliente/tenant | Multi-tenant (configurado por tb_integracao) |
| Status | ativo |
| Owner squad | a confirmar |
| Contato técnico cliente | a confirmar |
| Última revisão | 2026-08-14 |
Escopo
Fluxo completo
Rotas envolvidas
| Direção | Método | Rota | acao (middleware) | Função |
|---|---|---|---|---|
| Inbound | POST | /exam/pedido/totvs | (vazio — qualquer config ativa da integração) | Recebe pedidos TOTVS, grava MongoDB e gera worklist |
| Outbound | POST | /exam/redirect | REDIRECT | Converte laudo e envia ao url do adapter totvs |
:::caution OpenAPI
A rota POST /exam/pedido/totvs não está documentada em swaggerDocs.json hoje. O contrato outbound genérico está em Integra exame (POST /exam/redirect).
:::
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).
| Campo | Valor típico | Observação |
|---|---|---|
adapter | totvs | Deve bater com adapters/index.js |
acao | REDIRECT | Mapeada pelo middleware em POST /exam/redirect |
url | URL do endpoint TOTVS do cliente | Suporta [#variable#] via convertUrlVariable |
reportFormat | RTF, TEXT, HTML ou PDF | No modo legado, o adapter gera RTF e TEXT independentemente |
tipo_envio | JSON | Payload enviado como JSON no POST outbound |
base64 | conforme cliente | Repassado ao ReportConvertedService |
auth_type | TOKEN, BASIC_AUTH ou DEFAULT | Ver seção Autenticação |
automatic_retry | conforme tb_integracao | Usado pelo RetryService no fluxo de redirect |
medico_padrao_nome / medico_padrao_crm | se aplicável | Não usados diretamente pelo TotvsAdapter |
additional_settings.alternativeBody | true / ausente | Alterna entre payload estruturado TOTVS e payload legado |
additional_settings.resultOrigin | ex. "Imaging" | Só no modo alternativeBody; default "Imaging" |
additional_settings.alternativeMethod | ex. "put" | Método HTTP alternativo no externalRequest |
additional_settings.validateToken | se aplicável | Valida token antes do redirect |
headers_adicionais | JSON em tb_integracao | Headers extras no POST outbound |
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 → TOTVS)
Resolvida em exam.service.js → redirect():
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 |
Credenciais adicionais podem ser injetadas via headers_adicionais (JSON).
Rotação de credenciais: a confirmar (responsável / data).
Contrato
Inbound — POST /exam/pedido/totvs
Corpo esperado (recebePedidoTotvs):
json{"orders": [{"serviceOrderDate": "2026-01-15T10:30:00","patient": {"patientId": 12345,"name": "Paciente Exemplo","birthDate": "1980-05-20","gender": "M","cpf": "00000000000"},"exams": [{"examId": 987,"description": "RX Tórax PA","modality": "CR","code": "ACC-2026-001"}],"medicalInsurance": { "name": "Convênio Exemplo" },"practitioner": { "name": "Dr. Solicitante" }}]}
Comportamento:
- Valida campos obrigatórios; retorna
400se faltarem. - Deriva
accessionNumberdeexam.code(remove não-dígitos). - Cria registro de worklist por exame.
- Persiste pedido completo em MongoDB (
pedidoTotvs).
Resposta sucesso: { "message": "Orders received successfully" }.
Outbound — modo legado (alternativeBody ausente ou false)
Payload montado por TotvsAdapter.apply() e enviado ao url:
json{"accessionNumber": "2026001001","Laudortf": "<conteúdo RTF em base64 ou string conforme reportFormat>","Laudotxt": "<conteúdo TEXT>"}
O adapter sempre gera dois formatos (RTF com assinatura/data + TEXT), alternando reportFormat internamente.
Outbound — modo alternativeBody: true
Requer pedido prévio em MongoDB (via /exam/pedido/totvs). Busca por exams.accessionNumber.
json{"Id": "<sha256 aleatório>","CompanyId": 1,"ResultId": "<id do laudo convertido>","Identification": "<identification do pedido>","ProcessingDate": "<ultima_data_laudo>","ResultOrigin": "Imaging","Action": "I","PatientId": 12345,"OriginPatientId": "<patient.code>","ServiceOrder": 100,"OriginServiceOrder": "<code do pedido>","AttendanceId": 200,"OriginAttendanceId": "<attendance.code>","Base64Content": "<laudo convertido>","Exam": {"CompanyId": 1,"ServiceOrder": 100,"ExamId": 987,"Sequential": 1,"OriginExamId": "<exam.code>","MethodDescription": "RX Tórax PA","Results": []}}
| Campo | Regra |
|---|---|
Action | "I" se status_id === 1 (assinado); "A" caso contrário |
ResultOrigin | Default "Imaging"; sobrescrevível via additional_settings.resultOrigin |
Erros comuns (outbound)
| Erro | Causa |
|---|---|
order not found for accession number {acc} | Modo alternativeBody sem pedido prévio no MongoDB |
Erro ao redirecionar exame devido a laudo ainda não processado | Laudo sem PDF processado |
BLOCKED_BY_CONFIG | Bloqueio por redirectConditionals em additional_settings |
404 No integration found | Token inválido/inativo ou config acao=REDIRECT ausente |
Idempotência / retry
- Exames com
status_id = 5(revisão) passam por lógica de retentativa (RetryService) no controllerredirect. automatic_retryemtb_integracaocontrola retentativas automáticas.- Modo
alternativeBodygeraIdaleatório (SHA-256) a cada envio — não é idempotente por design.
Operação
| Item | Detalhe |
|---|---|
| Código adapter | mm-pacs-public-api/adapters/TotvsAdapter.js |
| Controller inbound | controllers/exam.controllers.js → recebePedidoTotvs |
| Controller outbound | controllers/exam.controllers.js → redirect |
| Service outbound | services/exam.service.js → redirect() |
| Persistência pedidos | MongoDB collection pedidoTotvs (mongodb/PedidoTOTVS.js) |
| Deploy / runbook | a confirmar |
| Monitoramento | Logs de integração (tipo 42 no redirect); logs de erro em recebePedidoTotvs |
| Escalação | a confirmar |
Evidências
- Homologação: a confirmar (responsável / data)
- Payloads de exemplo acima são anonimizados — não incluir PHI em PRs ou Bitrix
Rastreio
| Item | Valor |
|---|---|
| Tarefa Bitrix | a confirmar |
| PR código | a confirmar |
| PR documentação | a confirmar |
| URL publicada | /docs/interfaceReference/integrations/totvs |
| Ficha no repo | docs/interfaceReference/integrations/totvs/index.md |